diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/cxxrtl/cxxrtl.cc | 22 | ||||
| -rw-r--r-- | backends/cxxrtl/cxxrtl.h | 7 | 
2 files changed, 19 insertions, 10 deletions
| diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc index d1a855bf0..e4fa430f3 100644 --- a/backends/cxxrtl/cxxrtl.cc +++ b/backends/cxxrtl/cxxrtl.cc @@ -1166,8 +1166,7 @@ struct CxxrtlWorker {  		});  		dump_attrs(memory); -		f << indent << (writable_memories[memory] ? "" : "const ") -		            << "memory<" << memory->width << "> " << mangle(memory) +		f << indent << "memory<" << memory->width << "> " << mangle(memory)  		            << " { " << memory->size << "u";  		if (init_cells.empty()) {  			f << " };\n"; @@ -1425,8 +1424,6 @@ struct CxxrtlWorker {  					if (cell->getPort(ID(CLK)).is_wire())  						register_edge_signal(sigmap, cell->getPort(ID(CLK)),  							cell->parameters[ID(CLK_POLARITY)].as_bool() ? RTLIL::STp : RTLIL::STn); -					// The $adff and $dffsr cells are level-sensitive, not edge-sensitive (in spite of the fact that they -					// are inferred from an edge-sensitive Verilog process) and do not correspond to an edge-type sync rule.  				}  				// Similar for memory port cells.  				if (cell->type.in(ID($memrd), ID($memwr))) { @@ -1642,21 +1639,30 @@ struct CxxrtlBackend : public Backend {  		log("\n");  		log("    write_cxxrtl [options] [filename]\n");  		log("\n"); -		log("Write C++ code for simulating the design. The generated code requires a driver;\n"); -		log("the following simple driver is provided as an example:\n"); +		log("Write C++ code for simulating the design. The generated code requires a driver\n"); +		log("that instantiates the design, toggles its clock, and interacts with its ports.\n"); +		log("\n"); +		log("The following driver may be used as an example for a design with a single clock\n"); +		log("driving rising edge triggered flip-flops:\n");  		log("\n");  		log("    #include \"top.cc\"\n");  		log("\n");  		log("    int main() {\n");  		log("      cxxrtl_design::p_top top;\n"); +		log("      top.step();\n");  		log("      while (1) {\n"); -		log("        top.p_clk.next = value<1> {1u};\n"); -		log("        top.step();\n"); +		log("        /* user logic */\n");  		log("        top.p_clk.next = value<1> {0u};\n");  		log("        top.step();\n"); +		log("        top.p_clk.next = value<1> {1u};\n"); +		log("        top.step();\n");  		log("      }\n");  		log("    }\n");  		log("\n"); +		log("Note that CXXRTL simulations, just like the hardware they are simulating, are\n"); +		log("subject to race conditions. If, in then example above, the user logic would run\n"); +		log("simultaneously with the rising edge of the clock, the design would malfunction.\n"); +		log("\n");  		log("The following options are supported by this backend:\n");  		log("\n");  		log("    -header\n"); diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 593c31c28..fd390db79 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -604,12 +604,15 @@ struct memory {  		auto _ = {std::move(std::begin(init.data), std::end(init.data), data.begin() + init.offset)...};  	} -	value<Width> &operator [](size_t index) { +	// An operator for direct memory reads. May be used at any time during the simulation. +	const value<Width> &operator [](size_t index) const {  		assert(index < data.size());  		return data[index];  	} -	const value<Width> &operator [](size_t index) const { +	// An operator for direct memory writes. May only be used before the simulation is started. If used +	// after the simulation is started, the design may malfunction. +	value<Width> &operator [](size_t index) {  		assert(index < data.size());  		return data[index];  	} | 
