Merge remote-tracking branch 'origin/master' into xaig_dff

This commit is contained in:
Eddie Hung 2019-11-19 15:40:39 -08:00
commit 09ee96e8c2
228 changed files with 35110 additions and 24029 deletions

View File

@ -202,6 +202,52 @@ of how to use the Yosys API:
manual/PRESENTATION_Prog/my_cmd.cc
Script Passes
-------------
The ScriptPass base class can be used to implement passes that just call other passes,
like a script. Examples for such passes are:
techlibs/common/prep.cc
techlibs/common/synth.cc
In some cases it is easier to implement such a pass as regular pass, for example when
ScriptPass doesn't provide the type of flow control desired. (But many of the
script passes in Yosys that don't use ScriptPass simply predate the ScriptPass base
class.) Examples for such passes are:
passes/opt/opt.cc
passes/proc/proc.cc
Whether they use the ScriptPass base-class or not, a pass should always either
call other passes without doing any non-trivial work itself, or should implement
a non-trivial algorithm but not call any other passes. The reason for this is that
this helps containing complexity in individual passes and simplifies debugging the
entire system.
Exceptions to this rule should be rare and limited to cases where calling other
passes is optional and only happens when requested by the user (such as for
example `techmap -autoproc`), or where it is about commands that are "top-level
commands" in their own right, not components to be used in regular synthesis
flows (such as the `bugpoint` command).
A pass that would "naturally" call other passes and also do some work itself
should be re-written in one of two ways:
1) It could be re-written as script pass with the parts that are not calls
to other passes factored out into individual new passes. Usually in those
cases the new sub passes share the same prefix as the top-level script pass.
2) It could be re-written so that it already expects the design in a certain
state, expecting the calling script to set up this state before calling the
pass in questions.
Many back-ends are examples for the 2nd approach. For example, `write_aiger`
does not convert the design into AIG representation, but expects the design
to be already in this form, and prints an `Unsupported cell type` error
message otherwise.
Notes on the existing codebase
------------------------------

View File

@ -147,9 +147,9 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$
include Makefile.conf
endif
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
ifeq ($(ENABLE_PYOSYS),1)
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix)
@ -708,11 +708,17 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/various && bash run-test.sh
+cd tests/sat && bash run-test.sh
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+cd tests/svtypes && bash run-test.sh $(SEEDOPT)
+cd tests/proc && bash run-test.sh
+cd tests/opt && bash run-test.sh
+cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh
+cd tests/ice40 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/ice40 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/xilinx && bash run-test.sh $(SEEDOPT)
+cd tests/arch/ecp5 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
+cd tests/rpc && bash run-test.sh
@echo ""
@echo " Passed \"make test\"."

View File

@ -510,6 +510,8 @@ from SystemVerilog:
into a design with ``read_verilog``, all its packages are available to
SystemVerilog files being read into the same design afterwards.
- typedefs are supported (including inside packages)
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
ports are inputs or outputs are supported.

View File

@ -91,6 +91,9 @@ struct AigerWriter
} else
if (alias_map.count(bit)) {
a = bit2aig(alias_map.at(bit));
} else
if (initstate_bits.count(bit)) {
a = initstate_ff;
}
if (bit == State::Sx || bit == State::Sz)

View File

@ -1070,7 +1070,12 @@ struct BtorWorker
bad_properties.push_back(nid_en_and_not_a);
} else {
int nid = next_nid++;
btorf("%d bad %d\n", nid, nid_en_and_not_a);
string infostr = log_id(cell);
if (infostr[0] == '$' && cell->attributes.count("\\src")) {
infostr = cell->attributes.at("\\src").decode_string().c_str();
std::replace(infostr.begin(), infostr.end(), ' ', '_');
}
btorf("%d bad %d %s\n", nid, nid_en_and_not_a, infostr.c_str());
}
btorf_pop(log_id(cell));

View File

@ -1032,12 +1032,17 @@ class MkVcd:
print("$var integer 32 t smt_step $end", file=self.f)
print("$var event 1 ! smt_clock $end", file=self.f)
def vcdescape(n):
if n.startswith("$") or ":" in n:
return "\\" + n
return n
scope = []
for path in sorted(self.nets):
key, width = self.nets[path]
uipath = list(path)
if "." in uipath[-1]:
if "." in uipath[-1] and not uipath[-1].startswith("$"):
uipath = uipath[0:-1] + uipath[-1].split(".")
for i in range(len(uipath)):
uipath[i] = re.sub(r"\[([^\]]*)\]", r"<\1>", uipath[i])
@ -1048,15 +1053,13 @@ class MkVcd:
while uipath[:-1] != scope:
scopename = uipath[len(scope)]
if scopename.startswith("$"):
scopename = "\\" + scopename
print("$scope module %s $end" % scopename, file=self.f)
print("$scope module %s $end" % vcdescape(scopename), file=self.f)
scope.append(uipath[len(scope)])
if path in self.clocks and self.clocks[path][1] == "event":
print("$var event 1 %s %s $end" % (key, uipath[-1]), file=self.f)
print("$var event 1 %s %s $end" % (key, vcdescape(uipath[-1])), file=self.f)
else:
print("$var wire %d %s %s $end" % (width, key, uipath[-1]), file=self.f)
print("$var wire %d %s %s $end" % (width, key, vcdescape(uipath[-1])), file=self.f)
for i in range(len(scope)):
print("$upscope $end", file=self.f)

View File

@ -33,11 +33,11 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit;
int auto_name_counter, auto_name_offset, auto_name_digits;
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit;
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
std::map<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires, reg_ct;
std::string auto_prefix;
std::string auto_prefix, extmem_prefix;
RTLIL::Module *active_module;
dict<RTLIL::SigBit, RTLIL::State> active_initdata;
@ -371,13 +371,14 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
}
}
void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false, bool as_comment = false)
void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false, bool regattr = false, bool as_comment = false)
{
if (noattr)
return;
if (attr2comment)
as_comment = true;
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
if (it->first == "\\init" && regattr) continue;
f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
f << stringf(" = ");
if (modattr && (it->second == State::S0 || it->second == Const(0)))
@ -392,7 +393,7 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
{
dump_attributes(f, indent, wire->attributes);
dump_attributes(f, indent, wire->attributes, '\n', /*modattr=*/false, /*regattr=*/reg_wires.count(wire->name));
#if 0
if (wire->port_input && !wire->port_output)
f << stringf("%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
@ -1068,14 +1069,64 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset);
if (use_init)
{
f << stringf("%s" "initial begin\n", indent.c_str());
for (int i=0; i<size; i++)
if (extmem)
{
f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i);
dump_const(f, cell->parameters["\\INIT"].extract(i*width, width));
f << stringf(";\n");
std::string extmem_filename = stringf("%s-%d.mem", extmem_prefix.c_str(), extmem_counter++);
std::string extmem_filename_esc;
for (auto c : extmem_filename)
{
if (c == '\n')
extmem_filename_esc += "\\n";
else if (c == '\t')
extmem_filename_esc += "\\t";
else if (c < 32)
extmem_filename_esc += stringf("\\%03o", c);
else if (c == '"')
extmem_filename_esc += "\\\"";
else if (c == '\\')
extmem_filename_esc += "\\\\";
else
extmem_filename_esc += c;
}
f << stringf("%s" "initial $readmemb(\"%s\", %s);\n", indent.c_str(), extmem_filename_esc.c_str(), mem_id.c_str());
std::ofstream extmem_f(extmem_filename, std::ofstream::trunc);
if (extmem_f.fail())
log_error("Can't open file `%s' for writing: %s\n", extmem_filename.c_str(), strerror(errno));
else
{
for (int i=0; i<size; i++)
{
RTLIL::Const element = cell->parameters["\\INIT"].extract(i*width, width);
for (int j=0; j<element.size(); j++)
{
switch (element[element.size()-j-1])
{
case State::S0: extmem_f << '0'; break;
case State::S1: extmem_f << '1'; break;
case State::Sx: extmem_f << 'x'; break;
case State::Sz: extmem_f << 'z'; break;
case State::Sa: extmem_f << '_'; break;
case State::Sm: log_error("Found marker state in final netlist.");
}
}
extmem_f << '\n';
}
}
}
else
{
f << stringf("%s" "initial begin\n", indent.c_str());
for (int i=0; i<size; i++)
{
f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i);
dump_const(f, cell->parameters["\\INIT"].extract(i*width, width));
f << stringf(";\n");
}
f << stringf("%s" "end\n", indent.c_str());
}
f << stringf("%s" "end\n", indent.c_str());
}
// create a map : "edge clk" -> expressions within that clock domain
@ -1521,7 +1572,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw
bool got_default = false;
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true);
dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*regattr=*/false, /*as_comment=*/true);
if ((*it)->compare.size() == 0) {
if (got_default)
continue;
@ -1686,7 +1737,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
}
}
dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true);
dump_attributes(f, indent, module->attributes, '\n', /*modattr=*/true);
f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
bool keep_running = true;
for (int port_id = 1; keep_running; port_id++) {
@ -1776,8 +1827,16 @@ struct VerilogBackend : public Backend {
log(" deactivates this feature and instead will write string constants\n");
log(" as binary numbers.\n");
log("\n");
log(" -extmem\n");
log(" instead of initializing memories using assignments to individual\n");
log(" elements, use the '$readmemh' function to read initialization data\n");
log(" from a file. This data is written to a file named by appending\n");
log(" a sequential index to the Verilog filename and replacing the extension\n");
log(" with '.mem', e.g. 'write_verilog -extmem foo.v' writes 'foo-1.mem',\n");
log(" 'foo-2.mem' and so on.\n");
log("\n");
log(" -defparam\n");
log(" Use 'defparam' statements instead of the Verilog-2001 syntax for\n");
log(" use 'defparam' statements instead of the Verilog-2001 syntax for\n");
log(" cell parameters.\n");
log("\n");
log(" -blackboxes\n");
@ -1811,6 +1870,7 @@ struct VerilogBackend : public Backend {
nodec = false;
nohex = false;
nostr = false;
extmem = false;
defparam = false;
decimal = false;
siminit = false;
@ -1884,6 +1944,11 @@ struct VerilogBackend : public Backend {
nostr = true;
continue;
}
if (arg == "-extmem") {
extmem = true;
extmem_counter = 1;
continue;
}
if (arg == "-defparam") {
defparam = true;
continue;
@ -1911,6 +1976,12 @@ struct VerilogBackend : public Backend {
break;
}
extra_args(f, filename, args, argidx);
if (extmem)
{
if (filename.empty())
log_cmd_error("Option -extmem must be used with a filename.\n");
extmem_prefix = filename.substr(0, filename.rfind('.'));
}
design->sort();

View File

@ -1,41 +1,10 @@
// 50 MHz Clock
IO_LOC "clk" D11;
// LEDs
IO_LOC "leds[0]" D22;
IO_LOC "leds[1]" E22;
IO_LOC "leds[2]" G22;
IO_LOC "leds[3]" J22;
IO_LOC "leds[4]" L22;
IO_LOC "leds[5]" L19;
IO_LOC "leds[6]" L20;
IO_LOC "leds[7]" M21;
IO_LOC "leds[8]" N19;
IO_LOC "leds[9]" R19;
IO_LOC "leds[10]" T18;
IO_LOC "leds[11]" AA22;
IO_LOC "leds[12]" U18;
IO_LOC "leds[13]" V20;
IO_LOC "leds[14]" AA21;
IO_LOC "leds[15]" AB21;
// 7-Segment Display
IO_LOC "seg7dig[0]" E20;
IO_LOC "seg7dig[1]" G18;
IO_LOC "seg7dig[2]" G20;
IO_LOC "seg7dig[3]" F21;
IO_LOC "seg7dig[4]" J20;
IO_LOC "seg7dig[5]" H21;
IO_LOC "seg7dig[6]" H18;
IO_LOC "seg7dig[7]" D20;
IO_LOC "seg7sel[0]" C19;
IO_LOC "seg7sel[1]" B22;
IO_LOC "seg7sel[2]" C20;
IO_LOC "seg7sel[3]" C21;
// Switches
IO_LOC "sw[0]" AB20;
IO_LOC "sw[1]" AB19;
IO_LOC "sw[2]" AB18;
IO_LOC "sw[3]" AB17;
IO_LOC "clk" 35;
//IO_LOC "rst_n" 77;
IO_LOC "leds[0]" 79;
IO_LOC "leds[1]" 80;
IO_LOC "leds[2]" 81;
IO_LOC "leds[3]" 82;
IO_LOC "leds[4]" 83;
IO_LOC "leds[5]" 84;
IO_LOC "leds[6]" 85;
IO_LOC "leds[7]" 86;

View File

@ -1,9 +1,7 @@
module demo (
input clk,
input [3:0] sw,
output [15:0] leds,
output [7:0] seg7dig,
output [3:0] seg7sel
output unused
);
localparam PRESCALE = 20;
reg [PRESCALE+3:0] counter = 0;

16
examples/gowin/device.cfg Normal file
View File

@ -0,0 +1,16 @@
set JTAG regular_io = false
set SSPI regular_io = false
set MSPI regular_io = false
set READY regular_io = false
set DONE regular_io = false
set RECONFIG_N regular_io = false
set MODE regular_io = false
set CRC_check = true
set compress = false
set encryption = false
set security_bit_enable = true
set bsram_init_fuse_print = true
set download_speed = 250/100
set spi_flash_address = 0x00FFF000
set format = txt
set background_programming = false

8
examples/gowin/pnr.cfg Normal file
View File

@ -0,0 +1,8 @@
-sdf
-oc
-ibs
-posp
-o
-warning_all
-tt
-timing

View File

@ -1,8 +1,7 @@
#!/bin/bash
set -ex
yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v
$GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW2A55-PBGA484-6 \
-warning_all -out demo_out.v -rpt demo.rpt -tr demo_tr.html -bit demo.bit
$GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW1NR-9-QFN88-6 -pn GW1NR-LV9QN88C6/I5 -cfg device.cfg -bit -tr -ph -timing -gpa -rpt -warning_all
# post place&route simulation (icarus verilog)
if false; then

9
examples/gowin/run.tcl Normal file
View File

@ -0,0 +1,9 @@
# gw_sh run.tcl
exec yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v
add_file -cst demo.cst
add_file -sdc demo.sdc
add_file -vm demo_syn.v
add_file -cfg device.cfg
set_option -device GW1NR-9-QFN88-6
set_option -pn GW1NR-LV9QN88C6/I5
run_pnr -opt pnr.cfg

View File

@ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type)
X(AST_MODPORT)
X(AST_MODPORTMEMBER)
X(AST_PACKAGE)
X(AST_WIRETYPE)
X(AST_TYPEDEF)
#undef X
default:
log_abort();
@ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
was_checked = false;
range_valid = false;
range_swapped = false;
is_custom_type = false;
port_id = 0;
range_left = -1;
range_right = 0;

View File

@ -148,7 +148,10 @@ namespace AST
AST_INTERFACEPORTTYPE,
AST_MODPORT,
AST_MODPORTMEMBER,
AST_PACKAGE
AST_PACKAGE,
AST_WIRETYPE,
AST_TYPEDEF
};
// convert an node type to a string (e.g. for debug output)
@ -174,7 +177,7 @@ namespace AST
// node content - most of it is unused in most node types
std::string str;
std::vector<RTLIL::State> bits;
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized;
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type;
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;

View File

@ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_PACKAGE:
case AST_MODPORT:
case AST_MODPORTMEMBER:
case AST_TYPEDEF:
break;
case AST_INTERFACEPORT: {
// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'

View File

@ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX)
if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
const_fold = true;
if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
const_fold = true;
@ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
std::map<std::string, AstNode*> this_wire_scope;
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
if (node->type == AST_WIRE) {
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
for (auto c : node->children[0]->children) {
@ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
this_wire_scope[node->str] = node;
}
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) {
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
node->type == AST_TYPEDEF) {
backup_scope[node->str] = current_scope[node->str];
current_scope[node->str] = node;
}
}
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY)
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF)
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
did_something = true;
}
@ -780,6 +782,99 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
delete_children();
}
// resolve typedefs
if (type == AST_TYPEDEF) {
log_assert(children.size() == 1);
log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY);
while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param))
did_something = true;
log_assert(!children[0]->is_custom_type);
}
// resolve types of wires
if (type == AST_WIRE || type == AST_MEMORY) {
if (is_custom_type) {
log_assert(children.size() >= 1);
log_assert(children[0]->type == AST_WIRETYPE);
if (!current_scope.count(children[0]->str))
log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str());
AstNode *resolved_type = current_scope.at(children[0]->str);
if (resolved_type->type != AST_TYPEDEF)
log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str());
log_assert(resolved_type->children.size() == 1);
AstNode *templ = resolved_type->children[0];
// Remove type reference
delete children[0];
children.erase(children.begin());
// Ensure typedef itself is fully simplified
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
if (type == AST_WIRE)
type = templ->type;
is_reg = templ->is_reg;
is_logic = templ->is_logic;
is_signed = templ->is_signed;
is_string = templ->is_string;
is_custom_type = templ->is_custom_type;
range_valid = templ->range_valid;
range_swapped = templ->range_swapped;
range_left = templ->range_left;
range_right = templ->range_right;
// Insert clones children from template at beginning
for (int i = 0; i < GetSize(templ->children); i++)
children.insert(children.begin() + i, templ->children[i]->clone());
if (type == AST_MEMORY && GetSize(children) == 1) {
// Single-bit memories must have [0:0] range
AstNode *rng = new AstNode(AST_RANGE);
rng->children.push_back(AstNode::mkconst_int(0, true));
rng->children.push_back(AstNode::mkconst_int(0, true));
children.insert(children.begin(), rng);
}
did_something = true;
}
log_assert(!is_custom_type);
}
// resolve types of parameters
if (type == AST_LOCALPARAM || type == AST_PARAMETER) {
if (is_custom_type) {
log_assert(children.size() == 2);
log_assert(children[1]->type == AST_WIRETYPE);
if (!current_scope.count(children[1]->str))
log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
AstNode *resolved_type = current_scope.at(children[1]->str);
if (resolved_type->type != AST_TYPEDEF)
log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str());
log_assert(resolved_type->children.size() == 1);
AstNode *templ = resolved_type->children[0];
delete children[1];
children.pop_back();
// Ensure typedef itself is fully simplified
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
if (templ->type == AST_MEMORY)
log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
is_signed = templ->is_signed;
is_string = templ->is_string;
is_custom_type = templ->is_custom_type;
range_valid = templ->range_valid;
range_swapped = templ->range_swapped;
range_left = templ->range_left;
range_right = templ->range_right;
for (auto template_child : templ->children)
children.push_back(template_child->clone());
did_something = true;
}
log_assert(!is_custom_type);
}
// resolve constant prefixes
if (type == AST_PREFIX) {
if (children[0]->type != AST_CONSTANT) {
@ -1194,7 +1289,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_BLOCK && str.empty())
{
for (size_t i = 0; i < children.size(); i++)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
}
@ -1206,7 +1301,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
std::vector<AstNode*> new_children;
for (size_t i = 0; i < children.size(); i++)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) {
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) {
children[i]->simplify(false, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(children[i]);
current_scope[children[i]->str] = children[i];
@ -2906,7 +3001,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
}
}
if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0)
if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)
str = name_map[str];
std::map<std::string, std::string> backup_name_map;
@ -2914,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) {
child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {
if (backup_name_map.size() == 0)
backup_name_map = name_map;
std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
@ -2945,6 +3040,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
child->expand_genblock(index_var, prefix, name_map);
}
if (backup_name_map.size() > 0)
name_map.swap(backup_name_map);
}
@ -2998,6 +3094,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
uint32_t children_flags = 0;
int lhs_children_counter = 0;
if (type == AST_TYPEDEF)
return; // don't touch content of typedefs
if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
{
// mark all memories that are used in a complex expression on the left side of an assignment
@ -3155,6 +3254,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
if (type == AST_FUNCTION || type == AST_TASK)
return false;
if (type == AST_TYPEDEF)
return false;
if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
{
log_assert(children[0]->type == AST_CONSTANT);

View File

@ -174,6 +174,12 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (module == nullptr)
goto error;
if (!strcmp(cmd, ".blackbox"))
{
module->attributes["\\blackbox"] = RTLIL::Const(1);
continue;
}
if (!strcmp(cmd, ".end"))
{
for (auto &wp : wideports_cache)
@ -280,7 +286,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
goto error_with_reason;
}
module->rename(lastcell, p);
module->rename(lastcell, RTLIL::escape_id(p));
continue;
}

View File

@ -787,7 +787,18 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates)
void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo)
{
std::string netlist_name = nl->GetAtt(" \\top") ? nl->CellBaseName() : nl->Owner()->Name();
std::string module_name = nl->IsOperator() ? "$verific$" + netlist_name : RTLIL::escape_id(netlist_name);
std::string module_name = netlist_name;
if (nl->IsOperator()) {
module_name = "$verific$" + module_name;
} else {
if (*nl->Name()) {
module_name += "(";
module_name += nl->Name();
module_name += ")";
}
module_name = "\\" + module_name;
}
netlist = nl;
@ -1256,7 +1267,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (inst->Type() == PRIM_SVA_ASSERT || inst->Type() == PRIM_SVA_IMMEDIATE_ASSERT)
sva_asserts.insert(inst);
if (inst->Type() == PRIM_SVA_ASSUME || inst->Type() == PRIM_SVA_IMMEDIATE_ASSUME)
if (inst->Type() == PRIM_SVA_ASSUME || inst->Type() == PRIM_SVA_IMMEDIATE_ASSUME || inst->Type() == PRIM_SVA_RESTRICT)
sva_assumes.insert(inst);
if (inst->Type() == PRIM_SVA_COVER || inst->Type() == PRIM_SVA_IMMEDIATE_COVER)
@ -1396,8 +1407,20 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
import_verific_cells:
nl_todo.insert(inst->View());
RTLIL::Cell *cell = module->addCell(inst_name, inst->IsOperator() ?
std::string("$verific$") + inst->View()->Owner()->Name() : RTLIL::escape_id(inst->View()->Owner()->Name()));
std::string inst_type = inst->View()->Owner()->Name();
if (inst->View()->IsOperator()) {
inst_type = "$verific$" + inst_type;
} else {
if (*inst->View()->Name()) {
inst_type += "(";
inst_type += inst->View()->Name();
inst_type += ")";
}
inst_type = "\\" + inst_type;
}
RTLIL::Cell *cell = module->addCell(inst_name, inst_type);
if (inst->IsPrimitive() && mode_keep)
cell->attributes["\\keep"] = 1;
@ -1939,12 +1962,18 @@ struct VerificPass : public Pass {
log("Load the specified VHDL files into Verific.\n");
log("\n");
log("\n");
log(" verific -work <libname> {-sv|-vhdl|...} <hdl-file>\n");
log(" verific [-work <libname>] {-sv|-vhdl|...} <hdl-file>\n");
log("\n");
log("Load the specified Verilog/SystemVerilog/VHDL file into the specified library.\n");
log("(default library when -work is not present: \"work\")\n");
log("\n");
log("\n");
log(" verific [-L <libname>] {-sv|-vhdl|...} <hdl-file>\n");
log("\n");
log("Look up external definitions in the specified library.\n");
log("(-L may be used more than once)\n");
log("\n");
log("\n");
log(" verific -vlog-incdir <directory>..\n");
log("\n");
log("Add Verilog include directories.\n");
@ -2158,12 +2187,17 @@ struct VerificPass : public Pass {
goto check_error;
}
veri_file::RemoveAllLOptions();
for (; argidx < GetSize(args); argidx++)
{
if (args[argidx] == "-work" && argidx+1 < GetSize(args)) {
work = args[++argidx];
continue;
}
if (args[argidx] == "-L" && argidx+1 < GetSize(args)) {
veri_file::AddLOption(args[++argidx].c_str());
continue;
}
break;
}

View File

@ -490,13 +490,17 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
}
while (newline_count-- > 0)
return_char('\n');
// printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
defines_map[name] = value;
if (state == 2)
defines_with_args.insert(name);
else
defines_with_args.erase(name);
global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2);
if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) {
// printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
defines_map[name] = value;
if (state == 2)
defines_with_args.insert(name);
else
defines_with_args.erase(name);
global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2);
} else {
log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str());
}
continue;
}

View File

@ -553,6 +553,12 @@ struct VerilogDefines : public Pass {
log(" -Uname[=definition]\n");
log(" undefine the preprocessor symbol 'name'\n");
log("\n");
log(" -reset\n");
log(" clear list of defined preprocessor symbols\n");
log("\n");
log(" -list\n");
log(" list currently defined preprocessor symbols\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@ -588,6 +594,16 @@ struct VerilogDefines : public Pass {
design->verilog_defines.erase(name);
continue;
}
if (arg == "-reset") {
design->verilog_defines.clear();
continue;
}
if (arg == "-list") {
for (auto &it : design->verilog_defines) {
log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str());
}
continue;
}
break;
}

View File

@ -155,7 +155,7 @@ struct specify_rise_fall {
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id
%type <boolean> opt_signed opt_property unique_case_attr
%type <al> attr case_attr
@ -206,6 +206,7 @@ design:
task_func_decl design |
param_decl design |
localparam_decl design |
typedef_decl design |
package design |
interface design |
/* empty */;
@ -290,6 +291,9 @@ hierarchical_id:
$$ = $1;
};
hierarchical_type_id:
'(' hierarchical_id ')' { $$ = $2; };
module:
attr TOK_MODULE TOK_ID {
do_not_require_port_stubs = false;
@ -324,13 +328,13 @@ single_module_para:
astbuf1 = new AstNode(AST_PARAMETER);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_range single_param_decl |
} param_type single_param_decl |
attr TOK_LOCALPARAM {
if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_LOCALPARAM);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_range single_param_decl |
} param_type single_param_decl |
single_param_decl;
module_args_opt:
@ -426,6 +430,7 @@ package_body:
package_body package_body_stmt |;
package_body_stmt:
typedef_decl |
localparam_decl;
interface:
@ -452,7 +457,7 @@ interface_body:
interface_body interface_body_stmt |;
interface_body_stmt:
param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
modport_stmt;
non_opt_delay:
@ -475,8 +480,14 @@ wire_type:
};
wire_type_token_list:
wire_type_token | wire_type_token_list wire_type_token |
wire_type_token_io ;
wire_type_token |
wire_type_token_list wire_type_token |
wire_type_token_io |
hierarchical_type_id {
astbuf3->is_custom_type = true;
astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
astbuf3->children.back()->str = *$1;
};
wire_type_token_io:
TOK_INPUT {
@ -591,7 +602,7 @@ module_body:
/* empty */;
module_body_stmt:
task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
checker_decl:
@ -1149,12 +1160,20 @@ param_range:
}
};
param_type:
param_signed param_integer param_real param_range |
hierarchical_type_id {
astbuf1->is_custom_type = true;
astbuf1->children.push_back(new AstNode(AST_WIRETYPE));
astbuf1->children.back()->str = *$1;
};
param_decl:
attr TOK_PARAMETER {
astbuf1 = new AstNode(AST_PARAMETER);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_real param_range param_decl_list ';' {
} param_type param_decl_list ';' {
delete astbuf1;
};
@ -1163,7 +1182,7 @@ localparam_decl:
astbuf1 = new AstNode(AST_LOCALPARAM);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_real param_range param_decl_list ';' {
} param_type param_decl_list ';' {
delete astbuf1;
};
@ -1327,7 +1346,7 @@ wire_name:
if ($2 != NULL) {
if (node->is_input || node->is_output)
frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions.");
if (!astbuf2) {
if (!astbuf2 && !node->is_custom_type) {
AstNode *rng = new AstNode(AST_RANGE);
rng->children.push_back(AstNode::mkconst_int(0, true));
rng->children.push_back(AstNode::mkconst_int(0, true));
@ -1377,6 +1396,45 @@ assign_expr:
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
};
typedef_decl:
TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
if (astbuf2) {
frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions.");
} else {
astbuf2 = new AstNode(AST_RANGE);
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
}
}
if (astbuf2 && astbuf2->children.size() != 2)
frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
if (astbuf2)
astbuf1->children.push_back(astbuf2);
if ($5 != NULL) {
if (!astbuf2) {
AstNode *rng = new AstNode(AST_RANGE);
rng->children.push_back(AstNode::mkconst_int(0, true));
rng->children.push_back(AstNode::mkconst_int(0, true));
astbuf1->children.push_back(rng);
}
astbuf1->type = AST_MEMORY;
auto *rangeNode = $5;
if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) {
// SV array size [n], rewrite as [n-1:0]
rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true));
rangeNode->children.push_back(AstNode::mkconst_int(0, false));
}
astbuf1->children.push_back(rangeNode);
}
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
ast_stack.back()->children.back()->str = *$4;
};
cell_stmt:
attr TOK_ID {
astbuf1 = new AstNode(AST_CELL);
@ -1823,7 +1881,7 @@ simple_behavioral_stmt:
// this production creates the obligatory if-else shift/reduce conflict
behavioral_stmt:
defattr | assert | wire_decl | param_decl | localparam_decl |
defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |
non_opt_delay behavioral_stmt |
simple_behavioral_stmt ';' | ';' |
hierarchical_id attr {

View File

@ -253,6 +253,8 @@ class WContainer:
candidate = WType.from_string(arg.strip(), containing_file, line_number)
if candidate == None:
return None
if candidate.name == "void":
return None
cont.args.append(candidate)
return cont
@ -880,11 +882,8 @@ class WClass:
text += fun.gen_def_virtual()
return text
def gen_boost_py(self):
text = "\n\t\tclass_<" + self.name
if self.link_type == link_types.derive:
text += "Wrap, boost::noncopyable"
text += ">(\"" + self.name + "\""
def gen_boost_py_body(self):
text = ""
if self.printable_constrs() == 0 or not self.contains_default_constr():
text += ", no_init"
text += ")"
@ -907,6 +906,21 @@ class WClass:
text += "\n\t\t\t;\n"
return text
def gen_boost_py(self):
body = self.gen_boost_py_body()
if self.link_type == link_types.derive:
text = "\n\t\tclass_<" + self.name + ">(\"Cpp" + self.name + "\""
text += body
text += "\n\t\tclass_<" + self.name
text += "Wrap, boost::noncopyable"
text += ">(\"" + self.name + "\""
text += body
else:
text = "\n\t\tclass_<" + self.name + ">(\"" + self.name + "\""
text += body
return text
def contains_default_constr(self):
for c in self.found_constrs:
if len(c.args) == 0:
@ -974,6 +988,7 @@ blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Mo
enum_names = ["State","SyncType","ConstFlags"]
enums = [] #Do not edit
glbls = []
unowned_functions = []
@ -1723,6 +1738,159 @@ class WMember:
text += ")"
return text
class WGlobal:
orig_text = None
wtype = attr_types.default
name = None
containing_file = None
namespace = ""
is_const = False
def from_string(str_def, containing_file, line_number, namespace):
glbl = WGlobal()
glbl.orig_text = str_def
glbl.wtype = None
glbl.name = ""
glbl.containing_file = containing_file
glbl.namespace = namespace
glbl.is_const = False
if not str.startswith(str_def, "extern"):
return None
str_def = str_def[7:]
if str.startswith(str_def, "const "):
glbl.is_const = True
str_def = str_def[6:]
if str_def.count(" ") == 0:
return None
parts = split_list(str_def.strip(), " ")
prefix = ""
i = 0
for part in parts:
if part in ["unsigned", "long", "short"]:
prefix += part + " "
i += 1
else:
break
parts = parts[i:]
if len(parts) <= 1:
return None
glbl.wtype = WType.from_string(prefix + parts[0], containing_file, line_number)
if glbl.wtype == None:
return None
str_def = parts[1]
for part in parts[2:]:
str_def = str_def + " " + part
if str_def.find("(") != -1 or str_def.find(")") != -1 or str_def.find("{") != -1 or str_def.find("}") != -1:
return None
found = str_def.find(";")
if found == -1:
return None
found_eq = str_def.find("=")
if found_eq != -1:
found = found_eq
glbl.name = str_def[:found]
str_def = str_def[found+1:]
if glbl.name.find("*") == 0:
glbl.name = glbl.name.replace("*", "")
glbl.wtype.attr_type = attr_types.star
if glbl.name.find("&&") == 0:
glbl.name = glbl.name.replace("&&", "")
glbl.wtype.attr_type = attr_types.ampamp
if glbl.name.find("&") == 0:
glbl.name = glbl.name.replace("&", "")
glbl.wtype.attr_type = attr_types.amp
if(len(str_def.strip()) != 0):
return None
if len(glbl.name.split(",")) > 1:
glbl_list = []
for name in glbl.name.split(","):
name = name.strip();
glbl_list.append(WGlobal())
glbl_list[-1].orig_text = glbl.orig_text
glbl_list[-1].wtype = glbl.wtype
glbl_list[-1].name = name
glbl_list[-1].containing_file = glbl.containing_file
glbl_list[-1].namespace = glbl.namespace
glbl_list[-1].is_const = glbl.is_const
return glbl_list
return glbl
def gen_def(self):
text = "\n\t"
if self.is_const:
text += "const "
text += self.wtype.gen_text() + " get_var_py_" + self.name + "()"
text += "\n\t{\n\t\t"
if self.wtype.attr_type == attr_types.star:
text += "if(" + self.namespace + "::" + self.name + " == NULL)\n\t\t\t"
text += "throw std::runtime_error(\"" + self.namespace + "::" + self.name + " is NULL\");\n\t\t"
if self.wtype.name in known_containers:
text += self.wtype.gen_text_cpp()
else:
if self.is_const:
text += "const "
text += self.wtype.gen_text()
if self.wtype.name in classnames or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star):
text += "*"
text += " ret_ = "
if self.wtype.name in classnames:
text += self.wtype.name + "::get_py_obj("
if self.wtype.attr_type != attr_types.star:
text += "&"
text += self.namespace + "::" + self.name
if self.wtype.name in classnames:
text += ")"
text += ";"
if self.wtype.name in classnames:
text += "\n\t\treturn *ret_;"
elif self.wtype.name in known_containers:
text += known_containers[self.wtype.name].translate_cpp("ret_", self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star)
text += "\n\t\treturn ret____tmp;"
else:
text += "\n\t\treturn ret_;"
text += "\n\t}\n"
if self.is_const:
return text
ret = Attribute(self.wtype, "rhs");
if self.wtype.name in classnames:
text += "\n\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs)"
else:
text += "\n\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs)"
text += "\n\t{"
text += ret.gen_translation()
text += "\n\t\t" + self.namespace + "::" + self.name + " = " + ret.gen_call() + ";"
text += "\n\t}\n"
return text;
def gen_boost_py(self):
text = "\n\t\t\t.add_static_property(\"" + self.name + "\", &" + "YOSYS_PYTHON::get_var_py_" + self.name
if not self.is_const:
text += ", &YOSYS_PYTHON::set_var_py_" + self.name
text += ")"
return text
def concat_namespace(tuple_list):
if len(tuple_list) == 0:
return ""
@ -1859,6 +2027,16 @@ def parse_header(source):
else:
debug("\t\tFound member \"" + candidate.name + "\" of class \"" + class_[0].name + "\" of type \"" + candidate.wtype.name + "\"", 2)
class_[0].found_vars.append(candidate)
if candidate == None and class_ == None:
candidate = WGlobal.from_string(ugly_line, source.name, i, concat_namespace(namespaces))
if candidate != None:
if type(candidate) == list:
for c in candidate:
glbls.append(c)
debug("\tFound global \"" + c.name + "\" in namespace " + concat_namespace(namespaces), 2)
else:
glbls.append(candidate)
debug("\tFound global \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces), 2)
j = i
line = unpretty_string(line)
@ -1888,6 +2066,17 @@ def parse_header(source):
debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
class_[0].found_constrs.append(candidate)
continue
if class_ == None:
candidate = WGlobal.from_string(line, source.name, i, concat_namespace(namespaces))
if candidate != None:
if type(candidate) == list:
for c in candidate:
glbls.append(c)
debug("\tFound global \"" + c.name + "\" in namespace " + concat_namespace(namespaces), 2)
else:
glbls.append(candidate)
debug("\tFound global \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces), 2)
continue
if candidate != None:
while i < j:
i += 1
@ -1990,6 +2179,7 @@ def gen_wrappers(filename, debug_level_ = 0):
if len(class_.found_constrs) == 0:
class_.found_constrs.append(WConstructor(source.name, class_))
debug(str(len(unowned_functions)) + " functions are unowned", 1)
debug(str(len(unowned_functions)) + " global variables", 1)
for enum in enums:
debug("Enum " + assure_length(enum.name, len(max(enum_names, key=len)), True) + " contains " + assure_length(str(len(enum.values)), 2, False) + " values", 1)
debug("-"*col, 1)
@ -2025,10 +2215,15 @@ def gen_wrappers(filename, debug_level_ = 0):
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>
#include <boost/python.hpp>
#include <iosfwd> // std::streamsize
#include <iostream>
#include <boost/iostreams/concepts.hpp> // boost::iostreams::sink
#include <boost/iostreams/stream.hpp>
USING_YOSYS_NAMESPACE
namespace YOSYS_PYTHON {
struct YosysStatics{};
""")
for source in sources:
@ -2050,6 +2245,9 @@ namespace YOSYS_PYTHON {
for fun in unowned_functions:
wrapper_file.write(fun.gen_def())
for glbl in glbls:
wrapper_file.write(glbl.gen_def())
wrapper_file.write(""" struct Initializer
{
Initializer() {
@ -2068,12 +2266,89 @@ namespace YOSYS_PYTHON {
}
};
/// source: https://stackoverflow.com/questions/26033781/converting-python-io-object-to-stdostream-when-using-boostpython?noredirect=1&lq=1
/// @brief Type that implements the Boost.IOStream's Sink and Flushable
/// concept for writing data to Python object that support:
/// n = object.write(str) # n = None or bytes written
/// object.flush() # if flush exists, then it is callable
class PythonOutputDevice
{
public:
// This class models both the Sink and Flushable concepts.
struct category
: boost::iostreams::sink_tag,
boost::iostreams::flushable_tag
{};
explicit
PythonOutputDevice(boost::python::object object)
: object_(object)
{}
// Sink concept.
public:
typedef char char_type;
std::streamsize write(const char* buffer, std::streamsize buffer_size)
{
namespace python = boost::python;
// Copy the buffer to a python string.
python::str data(buffer, buffer_size);
// Invoke write on the python object, passing in the data. The following
// is equivalent to:
// n = object_.write(data)
python::extract<std::streamsize> bytes_written(
object_.attr("write")(data));
// Per the Sink concept, return the number of bytes written. If the
// Python return value provides a numeric result, then use it. Otherwise,
// such as the case of a File object, use the buffer_size.
return bytes_written.check()
? bytes_written
: buffer_size;
}
// Flushable concept.
public:
bool flush()
{
// If flush exists, then call it.
boost::python::object flush = object_.attr("flush");
if (!flush.is_none())
{
flush();
}
// Always return true. If an error occurs, an exception should be thrown.
return true;
}
private:
boost::python::object object_;
};
/// @brief Use an auxiliary function to adapt the legacy function.
void log_to_stream(boost::python::object object)
{
// Create an ostream that delegates to the python object.
boost::iostreams::stream<PythonOutputDevice>* output = new boost::iostreams::stream<PythonOutputDevice>(object);
Yosys::log_streams.insert(Yosys::log_streams.begin(), output);
};
BOOST_PYTHON_MODULE(libyosys)
{
using namespace boost::python;
class_<Initializer>("Initializer");
scope().attr("_hidden") = new Initializer();
def("log_to_stream", &log_to_stream);
""")
for enum in enums:
@ -2086,6 +2361,11 @@ namespace YOSYS_PYTHON {
for fun in unowned_functions:
wrapper_file.write(fun.gen_boost_py())
wrapper_file.write("\n\n\t\tclass_<YosysStatics>(\"Yosys\")\n")
for glbl in glbls:
wrapper_file.write(glbl.gen_boost_py())
wrapper_file.write("\t\t;\n")
wrapper_file.write("\n\t}\n}\n#endif")
def print_includes():

View File

@ -5,6 +5,7 @@ OBJS += passes/cmds/design.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/rename.o
OBJS += passes/cmds/autoname.o
OBJS += passes/cmds/connect.o
OBJS += passes/cmds/scatter.o
OBJS += passes/cmds/setundef.o

134
passes/cmds/autoname.cc Normal file
View File

@ -0,0 +1,134 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
int autoname_worker(Module *module)
{
dict<Cell*, pair<int, IdString>> proposed_cell_names;
dict<Wire*, pair<int, IdString>> proposed_wire_names;
dict<Wire*, int> wire_score;
int best_score = -1;
for (auto cell : module->selected_cells())
for (auto &conn : cell->connections())
for (auto bit : conn.second)
if (bit.wire != nullptr)
wire_score[bit.wire]++;
for (auto cell : module->selected_cells()) {
if (cell->name[0] == '$') {
for (auto &conn : cell->connections()) {
string suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] != '$') {
IdString new_name(bit.wire->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_cell_names[cell] = make_pair(score, new_name);
}
}
}
} else {
for (auto &conn : cell->connections()) {
string suffix = stringf("_%s", log_id(conn.first));
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] == '$') {
IdString new_name(cell->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_wire_names[bit.wire] = make_pair(score, new_name);
}
}
}
}
}
for (auto &it : proposed_cell_names) {
if (best_score*2 < it.second.first)
continue;
IdString n = module->uniquify(it.second.second);
log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
}
for (auto &it : proposed_wire_names) {
if (best_score*2 < it.second.first)
continue;
IdString n = module->uniquify(it.second.second);
log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
}
return proposed_cell_names.size() + proposed_wire_names.size();
}
struct AutonamePass : public Pass {
AutonamePass() : Pass("autoname", "automatically assign names to objects") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" autoname [selection]\n");
log("\n");
log("Assign auto-generated public names to objects with private names (the ones\n");
log("with $-prefix).\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-foo") {
// foo = true;
// continue;
// }
break;
}
log_header(design, "Executing AUTONAME pass.\n");
for (auto module : design->selected_modules())
{
int count = 0, iter = 0;
while (1) {
iter++;
int n = autoname_worker(module);
if (!n) break;
count += n;
}
if (count > 0)
log("Renamed %d objects in module %s (%d iterations).\n", count, log_id(module), iter);
}
}
} AutonamePass;
PRIVATE_NAMESPACE_END

View File

@ -158,22 +158,25 @@ static void detect_fsm(RTLIL::Wire *wire)
std::set<sig2driver_entry_t> cellport_list;
sig2user.find(sig_q, cellport_list);
auto sig_q_bits = sig_q.to_sigbit_pool();
for (auto &cellport : cellport_list)
{
RTLIL::Cell *cell = cellport.first;
bool set_output = false, clr_output = false;
if (cell->type == "$ne")
if (cell->type.in("$ne", "$reduce_or", "$reduce_bool"))
set_output = true;
if (cell->type == "$eq")
if (cell->type.in("$eq", "$logic_not", "$reduce_and"))
clr_output = true;
if (!set_output && !clr_output) {
clr_output = true;
if (set_output || clr_output) {
for (auto &port_it : cell->connections())
if (port_it.first != "\\A" || port_it.first != "\\Y")
clr_output = false;
if (cell->input(port_it.first))
for (auto bit : assign_map(port_it.second))
if (bit.wire != nullptr && !sig_q_bits.count(bit))
goto next_cellport;
}
if (set_output || clr_output) {
@ -184,6 +187,7 @@ static void detect_fsm(RTLIL::Wire *wire)
ce.set(sig, val);
}
}
next_cellport:;
}
SigSpec sig_y = sig_d, sig_undef;

View File

@ -143,13 +143,18 @@ struct WreduceWorker
SigSpec sig_d = mi.sigmap(cell->getPort(ID(D)));
SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q)));
Const initval;
bool is_adff = (cell->type == ID($adff));
Const initval, arst_value;
int width_before = GetSize(sig_q);
if (width_before == 0)
return;
if (cell->parameters.count(ID(ARST_VALUE))) {
arst_value = cell->parameters[ID(ARST_VALUE)];
}
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
bool sign_ext = !zero_ext;
@ -163,7 +168,8 @@ struct WreduceWorker
for (int i = GetSize(sig_q)-1; i >= 0; i--)
{
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx) &&
(!is_adff || i >= GetSize(arst_value) || arst_value[i] == State::S0 || arst_value[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
@ -171,7 +177,8 @@ struct WreduceWorker
continue;
}
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1] &&
(!is_adff || i >= GetSize(arst_value) || arst_value[i] == arst_value[i-1])) {
module->connect(sig_q[i], sig_q[i-1]);
remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
@ -214,7 +221,6 @@ struct WreduceWorker
// Narrow ARST_VALUE parameter to new size.
if (cell->parameters.count(ID(ARST_VALUE))) {
Const arst_value = cell->getParam(ID(ARST_VALUE));
arst_value.bits.resize(GetSize(sig_q));
cell->setParam(ID(ARST_VALUE), arst_value);
}

View File

@ -1,5 +1,5 @@
%_pm.h: passes/pmgen/pmgen.py %.pmg
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^)
$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^)
# --------------------------------------
@ -38,7 +38,7 @@ PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
PEEPOPT_PATTERN += passes/pmgen/peepopt_dffmux.pmg
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^)
$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
# --------------------------------------

140
passes/pmgen/generate.h Normal file
View File

@ -0,0 +1,140 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef PMGEN_GENERATE
#define PMGEN_GENERATE
#define GENERATE_PATTERN(pmclass, pattern) \
generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
void pmtest_addports(Module *module)
{
pool<SigBit> driven_bits, used_bits;
SigMap sigmap(module);
int icnt = 0, ocnt = 0;
for (auto cell : module->cells())
for (auto conn : cell->connections())
{
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
used_bits.insert(bit);
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
driven_bits.insert(bit);
}
for (auto wire : vector<Wire*>(module->wires()))
{
SigSpec ibits, obits;
for (auto bit : sigmap(wire)) {
if (!used_bits.count(bit))
obits.append(bit);
if (!driven_bits.count(bit))
ibits.append(bit);
}
if (!ibits.empty()) {
Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
w->port_input = true;
module->connect(ibits, w);
}
if (!obits.empty()) {
Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
w->port_output = true;
module->connect(w, obits);
}
}
module->fixup_ports();
}
template <class pm>
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
{
log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
int modcnt = 0;
int maxmodcnt = 100;
int maxsubcnt = 4;
int timeout = 0;
vector<Module*> mods;
while (modcnt < maxmodcnt)
{
int submodcnt = 0, itercnt = 0, cellcnt = 0;
Module *mod = design->addModule(NEW_ID);
while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
{
if (timeout++ > 10000)
log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n");
pm matcher(mod, mod->cells());
matcher.rng(1);
matcher.rngseed += modcnt;
matcher.rng(1);
matcher.rngseed += submodcnt;
matcher.rng(1);
matcher.rngseed += itercnt;
matcher.rng(1);
matcher.rngseed += cellcnt;
matcher.rng(1);
if (GetSize(mod->cells()) != cellcnt)
{
bool found_match = false;
run(matcher, [&](){ found_match = true; });
cellcnt = GetSize(mod->cells());
if (found_match) {
Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
pmclass, pattern, modcnt++));
log("Creating module %s with %d cells.\n", log_id(m), cellcnt);
mod->cloneInto(m);
pmtest_addports(m);
mods.push_back(m);
submodcnt++;
timeout = 0;
}
}
matcher.generate_mode = true;
run(matcher, [](){});
}
if (submodcnt && maxsubcnt < (1 << 16))
maxsubcnt *= 2;
design->remove(mod);
}
Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern));
log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods));
for (auto mod : mods) {
Cell *c = m->addCell(mod->name, mod->name);
for (auto port : mod->ports) {
Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port)));
c->setPort(port, w);
}
}
pmtest_addports(m);
}
#endif

View File

@ -24,8 +24,11 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
bool did_something;
dict<SigBit, State> initbits;
pool<SigBit> rminitbits;
#include "passes/pmgen/peepopt_pm.h"
#include "generate.h"
struct PeepoptPass : public Pass {
PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { }
@ -40,27 +43,86 @@ struct PeepoptPass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string genmode;
log_header(design, "Executing PEEPOPT pass (run peephole optimizers).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-singleton") {
// singleton_mode = true;
// continue;
// }
if (args[argidx] == "-generate" && argidx+1 < args.size()) {
genmode = args[++argidx];
continue;
}
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules()) {
if (!genmode.empty())
{
initbits.clear();
rminitbits.clear();
if (genmode == "shiftmul")
GENERATE_PATTERN(peepopt_pm, shiftmul);
else if (genmode == "muldiv")
GENERATE_PATTERN(peepopt_pm, muldiv);
else if (genmode == "dffmux")
GENERATE_PATTERN(peepopt_pm, dffmux);
else
log_abort();
return;
}
for (auto module : design->selected_modules())
{
did_something = true;
while (did_something) {
while (did_something)
{
did_something = false;
peepopt_pm pm(module, module->selected_cells());
initbits.clear();
rminitbits.clear();
peepopt_pm pm(module);
for (auto w : module->wires()) {
auto it = w->attributes.find(ID(init));
if (it != w->attributes.end()) {
SigSpec sig = pm.sigmap(w);
Const val = it->second;
int len = std::min(GetSize(sig), GetSize(val));
for (int i = 0; i < len; i++) {
if (sig[i].wire == nullptr)
continue;
if (val[i] != State::S0 && val[i] != State::S1)
continue;
initbits[sig[i]] = val[i];
}
}
}
pm.setup(module->selected_cells());
pm.run_shiftmul();
pm.run_muldiv();
pm.run_dffmux();
for (auto w : module->wires()) {
auto it = w->attributes.find(ID(init));
if (it != w->attributes.end()) {
SigSpec sig = pm.sigmap(w);
Const &val = it->second;
int len = std::min(GetSize(sig), GetSize(val));
for (int i = 0; i < len; i++) {
if (rminitbits.count(sig[i]))
val[i] = State::Sx;
}
}
}
initbits.clear();
rminitbits.clear();
}
}
}

View File

@ -60,12 +60,13 @@ code
SigSpec Q = port(dff, \Q);
int width = GetSize(D);
SigSpec &dffD = dff->connections_.at(\D);
SigSpec &dffQ = dff->connections_.at(\Q);
Const init;
for (const auto &b : Q) {
auto it = b.wire->attributes.find(\init);
init.bits.push_back(it == b.wire->attributes.end() ? State::Sx : it->second[b.offset]);
SigSpec dffD = dff->getPort(\D);
SigSpec dffQ = dff->getPort(\Q);
Const initval;
for (auto b : Q) {
auto it = initbits.find(b);
initval.bits.push_back(it == initbits.end() ? State::Sx : it->second);
}
auto cmpx = [=](State lhs, State rhs) {
@ -76,56 +77,68 @@ code
int i = width-1;
while (i > 1) {
log_dump(i, D[i], D[i-1], rst[i], rst[i-1], init[i], init[i-1]);
if (D[i] != D[i-1])
break;
if (!cmpx(rst[i], rst[i-1]))
break;
if (!cmpx(init[i], init[i-1]))
if (!cmpx(initval[i], initval[i-1]))
break;
if (!cmpx(rst[i], init[i]))
if (!cmpx(rst[i], initval[i]))
break;
rminitbits.insert(Q[i]);
module->connect(Q[i], Q[i-1]);
i--;
}
if (i < width-1) {
did_something = true;
if (cemux) {
SigSpec &ceA = cemux->connections_.at(\A);
SigSpec &ceB = cemux->connections_.at(\B);
SigSpec &ceY = cemux->connections_.at(\Y);
SigSpec ceA = cemux->getPort(\A);
SigSpec ceB = cemux->getPort(\B);
SigSpec ceY = cemux->getPort(\Y);
ceA.remove(i, width-1-i);
ceB.remove(i, width-1-i);
ceY.remove(i, width-1-i);
cemux->setPort(\A, ceA);
cemux->setPort(\B, ceB);
cemux->setPort(\Y, ceY);
cemux->fixup_parameters();
blacklist(cemux);
}
if (rstmux) {
SigSpec &rstA = rstmux->connections_.at(\A);
SigSpec &rstB = rstmux->connections_.at(\B);
SigSpec &rstY = rstmux->connections_.at(\Y);
SigSpec rstA = rstmux->getPort(\A);
SigSpec rstB = rstmux->getPort(\B);
SigSpec rstY = rstmux->getPort(\Y);
rstA.remove(i, width-1-i);
rstB.remove(i, width-1-i);
rstY.remove(i, width-1-i);
rstmux->setPort(\A, rstA);
rstmux->setPort(\B, rstB);
rstmux->setPort(\Y, rstY);
rstmux->fixup_parameters();
blacklist(rstmux);
}
dffD.remove(i, width-1-i);
dffQ.remove(i, width-1-i);
dff->setPort(\D, dffD);
dff->setPort(\Q, dffQ);
dff->fixup_parameters();
blacklist(dff);
log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed top %d bits.\n", log_id(module), log_id(dff), log_id(cemux, "n/a"), log_id(rstmux, "n/a"), width-1-i);
width = i+1;
}
if (cemux) {
SigSpec &ceA = cemux->connections_.at(\A);
SigSpec &ceB = cemux->connections_.at(\B);
SigSpec &ceY = cemux->connections_.at(\Y);
SigSpec ceA = cemux->getPort(\A);
SigSpec ceB = cemux->getPort(\B);
SigSpec ceY = cemux->getPort(\Y);
int count = 0;
for (int i = width-1; i >= 0; i--) {
if (D[i].wire)
continue;
if (cmpx(rst[i], D[i].data) && cmpx(init[i], D[i].data)) {
if (cmpx(rst[i], D[i].data) && cmpx(initval[i], D[i].data)) {
count++;
rminitbits.insert(Q[i]);
module->connect(Q[i], D[i]);
ceA.remove(i);
ceB.remove(i);
@ -134,10 +147,21 @@ code
dffQ.remove(i);
}
}
if (count > 0) {
if (count > 0)
{
did_something = true;
cemux->setPort(\A, ceA);
cemux->setPort(\B, ceB);
cemux->setPort(\Y, ceY);
cemux->fixup_parameters();
blacklist(cemux);
dff->setPort(\D, dffD);
dff->setPort(\Q, dffQ);
dff->fixup_parameters();
blacklist(dff);
log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed %d constant bits.\n", log_id(module), log_id(dff), log_id(cemux), log_id(rstmux, "n/a"), count);
}
}

View File

@ -362,6 +362,7 @@ with open(outfile, "w") as f:
print(" Module *module;", file=f)
print(" SigMap sigmap;", file=f)
print(" std::function<void()> on_accept;", file=f)
print(" bool setup_done;", file=f)
print(" bool generate_mode;", file=f)
print(" int accept_cnt;", file=f)
print("", file=f)
@ -477,7 +478,17 @@ with open(outfile, "w") as f:
print("", file=f)
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
print(" module(module), sigmap(module), generate_mode(false), rngseed(12345678) {", file=f)
print(" module(module), sigmap(module), setup_done(false), generate_mode(false), rngseed(12345678) {", file=f)
print(" setup(cells);", file=f)
print(" }", file=f)
print("", file=f)
print(" {}_pm(Module *module) :".format(prefix), file=f)
print(" module(module), sigmap(module), setup_done(false), generate_mode(false), rngseed(12345678) {", file=f)
print(" }", file=f)
print("", file=f)
print(" void setup(const vector<Cell*> &cells) {", file=f)
for current_pattern in sorted(patterns.keys()):
for s, t in sorted(udata_types[current_pattern].items()):
if t.endswith("*"):
@ -485,6 +496,8 @@ with open(outfile, "w") as f:
else:
print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f)
current_pattern = None
print(" log_assert(!setup_done);", file=f)
print(" setup_done = true;", file=f)
print(" for (auto port : module->ports)", file=f)
print(" add_siguser(module->wire(port), nullptr);", file=f)
print(" for (auto cell : module->cells())", file=f)
@ -539,6 +552,7 @@ with open(outfile, "w") as f:
for current_pattern in sorted(patterns.keys()):
print(" int run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f)
print(" log_assert(setup_done);", file=f)
print(" accept_cnt = 0;", file=f)
print(" on_accept = on_accept_f;", file=f)
print(" rollback = 0;", file=f)

View File

@ -23,13 +23,11 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
// for peepopt_pm
bool did_something;
#include "passes/pmgen/test_pmgen_pm.h"
#include "passes/pmgen/ice40_dsp_pm.h"
#include "passes/pmgen/xilinx_srl_pm.h"
#include "passes/pmgen/peepopt_pm.h"
#include "generate.h"
void reduce_chain(test_pmgen_pm &pm)
{
@ -118,123 +116,6 @@ void opt_eqpmux(test_pmgen_pm &pm)
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
}
#define GENERATE_PATTERN(pmclass, pattern) \
generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
void pmtest_addports(Module *module)
{
pool<SigBit> driven_bits, used_bits;
SigMap sigmap(module);
int icnt = 0, ocnt = 0;
for (auto cell : module->cells())
for (auto conn : cell->connections())
{
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
used_bits.insert(bit);
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
driven_bits.insert(bit);
}
for (auto wire : vector<Wire*>(module->wires()))
{
SigSpec ibits, obits;
for (auto bit : sigmap(wire)) {
if (!used_bits.count(bit))
obits.append(bit);
if (!driven_bits.count(bit))
ibits.append(bit);
}
if (!ibits.empty()) {
Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
w->port_input = true;
module->connect(ibits, w);
}
if (!obits.empty()) {
Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
w->port_output = true;
module->connect(w, obits);
}
}
module->fixup_ports();
}
template <class pm>
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
{
log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
int modcnt = 0;
int maxmodcnt = 100;
int maxsubcnt = 4;
int timeout = 0;
vector<Module*> mods;
while (modcnt < maxmodcnt)
{
int submodcnt = 0, itercnt = 0, cellcnt = 0;
Module *mod = design->addModule(NEW_ID);
while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
{
if (timeout++ > 10000)
log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n");
pm matcher(mod, mod->cells());
matcher.rng(1);
matcher.rngseed += modcnt;
matcher.rng(1);
matcher.rngseed += submodcnt;
matcher.rng(1);
matcher.rngseed += itercnt;
matcher.rng(1);
matcher.rngseed += cellcnt;
matcher.rng(1);
if (GetSize(mod->cells()) != cellcnt)
{
bool found_match = false;
run(matcher, [&](){ found_match = true; });
cellcnt = GetSize(mod->cells());
if (found_match) {
Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
pmclass, pattern, modcnt++));
log("Creating module %s with %d cells.\n", log_id(m), cellcnt);
mod->cloneInto(m);
pmtest_addports(m);
mods.push_back(m);
submodcnt++;
timeout = 0;
}
}
matcher.generate_mode = true;
run(matcher, [](){});
}
if (submodcnt && maxsubcnt < (1 << 16))
maxsubcnt *= 2;
design->remove(mod);
}
Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern));
log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods));
for (auto mod : mods) {
Cell *c = m->addCell(mod->name, mod->name);
for (auto port : mod->ports) {
Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port)));
c->setPort(port, w);
}
}
pmtest_addports(m);
}
struct TestPmgenPass : public Pass {
TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
void help() YS_OVERRIDE
@ -355,12 +236,6 @@ struct TestPmgenPass : public Pass {
if (pattern == "xilinx_srl.variable")
return GENERATE_PATTERN(xilinx_srl_pm, variable);
if (pattern == "peepopt-muldiv")
return GENERATE_PATTERN(peepopt_pm, muldiv);
if (pattern == "peepopt-shiftmul")
return GENERATE_PATTERN(peepopt_pm, shiftmul);
log_cmd_error("Unknown pattern: %s\n", pattern.c_str());
}

View File

@ -98,16 +98,16 @@ code sigA sigB sigC sigD sigM clock
if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = 0; i < GetSize(P); i++) {
if (nusers(P[i]) <= 1)
for (i = GetSize(P)-1; i >= 0; i--)
if (nusers(P[i]) > 1)
break;
sigM.append(P[i]);
}
i++;
log_assert(nusers(P.extract_end(i)) <= 1);
// This sigM could have no users if downstream sinks (e.g. $add) is
// narrower than $mul result, for example
if (sigM.empty())
if (i == 0)
reject;
sigM = P.extract(0, i);
}
else
sigM = P;
@ -460,6 +460,8 @@ arg argD argQ clock
code
dff = nullptr;
if (GetSize(argQ) == 0)
reject;
for (const auto &c : argQ.chunks()) {
// Abandon matches when 'Q' is a constant
if (!c.wire)

View File

@ -63,12 +63,12 @@ code sigC sigP clock
if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = 0; i < GetSize(P); i++) {
if (nusers(P[i]) <= 1)
for (i = GetSize(P)-1; i >= 0; i--)
if (nusers(P[i]) > 1)
break;
sigP.append(P[i]);
}
i++;
log_assert(nusers(P.extract_end(i)) <= 1);
sigP = P.extract(0, i);
}
else
sigP = P;

View File

@ -262,10 +262,14 @@ struct ExtractFaWorker
pool<SigBit> new_leaves = leaves;
new_leaves.erase(bit);
if (cell->hasPort(ID::A)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::A))));
if (cell->hasPort(ID::B)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::B))));
if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C)))));
if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D)))));
for (auto port : {ID::A, ID::B, ID(C), ID(D)}) {
if (!cell->hasPort(port))
continue;
auto bit = sigmap(SigBit(cell->getPort(port)));
if (!bit.wire)
continue;
new_leaves.insert(bit);
}
if (GetSize(new_leaves) > maxbreadth)
continue;

View File

@ -394,7 +394,7 @@ struct FlowGraph
pair<pool<RTLIL::SigBit>, pool<RTLIL::SigBit>> edge_cut()
{
pool<RTLIL::SigBit> x, xi;
pool<RTLIL::SigBit> x = {source}, xi; // X and X̅ in the paper
NodePrime source_prime = {source, true};
pool<NodePrime> visited;
@ -437,6 +437,7 @@ struct FlowGraph
for (auto collapsed_node : collapsed[sink])
xi.insert(collapsed_node);
log_assert(x[source] && !xi[source]);
log_assert(!x[sink] && xi[sink]);
return {x, xi};
}
@ -1050,7 +1051,7 @@ struct FlowmapWorker
auto cut_inputs = cut_lut_at_gate(lut, lut_gate);
pool<RTLIL::SigBit> gate_inputs = cut_inputs.first, other_inputs = cut_inputs.second;
if (gate_inputs.empty() && (int)other_inputs.size() == order)
if (gate_inputs.empty() && (int)other_inputs.size() >= order)
{
if (debug_relax)
log(" Breaking would result in a (k+1)-LUT.\n");

View File

@ -9,12 +9,12 @@ GENFILES += techlibs/common/simcells_help.inc
techlibs/common/simlib_help.inc: techlibs/common/cellhelp.py techlibs/common/simlib.v
$(Q) mkdir -p techlibs/common
$(P) python3 $^ > $@.new
$(P) $(PYTHON_EXECUTABLE) $^ > $@.new
$(Q) mv $@.new $@
techlibs/common/simcells_help.inc: techlibs/common/cellhelp.py techlibs/common/simcells.v
$(Q) mkdir -p techlibs/common
$(P) python3 $^ > $@.new
$(P) $(PYTHON_EXECUTABLE) $^ > $@.new
$(Q) mv $@.new $@
kernel/register.o: techlibs/common/simlib_help.inc techlibs/common/simcells_help.inc

View File

@ -7,7 +7,7 @@
// with n <= k inputs should be techmapped in this way, because this shortens the critical path
// from n to 1 by avoiding carry chains.
(* techmap_celltype = "$eq $ne $lt $le $gt $ge" *)
(* techmap_celltype = "$lt $le $gt $ge" *)
module _90_lut_cmp_ (A, B, Y);
parameter A_SIGNED = 0;

View File

@ -27,12 +27,12 @@ EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
techlibs/ecp5/brams_init.mk: techlibs/ecp5/brams_init.py
$(Q) mkdir -p techlibs/ecp5
$(P) python3 $<
$(P) $(PYTHON_EXECUTABLE) $<
$(Q) touch $@
techlibs/ecp5/brams_connect.mk: techlibs/ecp5/brams_connect.py
$(Q) mkdir -p techlibs/ecp5
$(P) python3 $<
$(P) $(PYTHON_EXECUTABLE) $<
$(Q) touch $@

View File

@ -333,6 +333,13 @@ module ECLKSYNCB(
);
endmodule
(* blackbox *)
module ECLKBRIDGECS(
input CLK0, CLK1, SEL,
output ECSOUT
);
endmodule
(* blackbox *)
module DCCA(
input CLKI, CE,

View File

@ -23,15 +23,15 @@ module FD1S3JX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLI
// module FL1S3AY(); endmodule
// Diamond I/O registers
module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
// TODO: Diamond I/O latches
// module IFS1S1B(input PD, D, SCLK, output Q); endmodule

View File

@ -297,6 +297,7 @@ struct SynthEcp5Pass : public ScriptPass
run("simplemap");
run("ecp5_ffinit");
run("ecp5_gsr");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
@ -313,9 +314,9 @@ struct SynthEcp5Pass : public ScriptPass
if (abc9) {
run("read_verilog -icells -lib +/ecp5/abc9_model.v");
if (nowidelut)
run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200");
run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs");
else
run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200");
run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs");
run("techmap -map +/ecp5/abc9_unmap.v");
} else {
if (nowidelut)
@ -338,6 +339,7 @@ struct SynthEcp5Pass : public ScriptPass
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");

View File

@ -17,6 +17,18 @@ module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE
module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
module \$_DLATCH_N_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = !E ? D : Q;
endmodule
module \$_DLATCH_P_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = E ? D : Q;
endmodule
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;

View File

@ -59,7 +59,9 @@ module EFX_FF(
assign ce = CE_POLARITY ? CE : ~CE;
assign sr = SR_POLARITY ? SR : ~SR;
assign d = D_POLARITY ? D : ~D;
initial Q = 1'b0;
generate
if (SR_SYNC == 1)
begin

View File

@ -15,3 +15,13 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh))
EXTRA_OBJS += techlibs/gowin/brams_init.mk
.SECONDARY: techlibs/gowin/brams_init.mk
techlibs/gowin/brams_init.mk: techlibs/gowin/brams_init.py
$(Q) mkdir -p techlibs/gowin
$(P) python3 $<
$(Q) touch $@
techlibs/gowin/bram_init_16.vh: techlibs/gowin/brams_init.mk
$(eval $(call add_gen_share_file,share/gowin,techlibs/gowin/bram_init_16.vh))

View File

@ -40,15 +40,15 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
wire [Y_WIDTH-1:0] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH-1:0] BB = B_buf;
wire [Y_WIDTH-1:0] C = {CO, CI};
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
ALU #(.ALU_MODE(32'b0))
ALU #(.ALU_MODE(2)) // ADDSUB I3 ? add : sub
alu(.I0(AA[i]),
.I1(BB[i]),
.I3(1'b0),
.I3(~BI),
.CIN(C[i]),
.COUT(CO[i]),
.SUM(Y[i])

View File

@ -1,6 +1,7 @@
bram $__GW1NR_SDP
# uncomment when done
# init 1
init 1
abits 9 @a9d36
dbits 32 @a9d36
abits 10 @a10d18
dbits 16 @a10d18
abits 11 @a11d9
@ -14,7 +15,8 @@ bram $__GW1NR_SDP
groups 2
ports 1 1
wrmode 1 0
enable 1 1 @a10d18
enable 4 1 @a9d36
enable 2 1 @a10d18
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
transp 0 0
clocks 2 3
@ -24,6 +26,6 @@ endbram
match $__GW1NR_SDP
min bits 2048
min efficiency 5
shuffle_enable B
shuffle_enable A
make_transp
endmatch

8
techlibs/gowin/brams_init.py Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env python3
with open("techlibs/gowin/bram_init_16.vh", "w") as f:
for i in range(0, 0x40):
low = i << 8
hi = ((i+1) << 8)-1
snippet = "INIT[%d:%d]" % (hi, low)
print(".INIT_RAM_%02X({%s})," % (i, snippet), file=f)

View File

@ -8,26 +8,28 @@
module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 16;
parameter CFG_ENABLE_A = 3;
parameter [16383:0] INIT = 16384'hx;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter CFG_ENABLE_A = 1;
parameter [16383:0] INIT = 16384'hx;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
input CLK2;
input CLK3;
input [CFG_ABITS-1:0] A1ADDR;
input [CFG_DBITS-1:0] A1DATA;
input [CFG_ENABLE_A-1:0] A1EN;
input [CFG_ENABLE_A-1:0] A1EN;
input [CFG_ABITS-1:0] B1ADDR;
output [CFG_DBITS-1:0] B1DATA;
input B1EN;
wire [31-CFG_DBITS:0] open;
generate if (CFG_DBITS == 1) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(1),
.BIT_WIDTH_1(1),
@ -38,10 +40,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
.DO({open, B1DATA}),
.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS == 2) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(2),
.BIT_WIDTH_1(2),
@ -52,10 +58,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
.DO({open, B1DATA}),
.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 4) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(4),
.BIT_WIDTH_1(4),
@ -66,10 +76,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0),
.WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
.DO({open, B1DATA}),
.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 8) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(8),
.BIT_WIDTH_1(8),
@ -80,10 +94,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
.DO({open, B1DATA}),
.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 16) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(16),
.BIT_WIDTH_1(16),
@ -91,10 +109,31 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.RESET_MODE("SYNC")
) _TECHMAP_REPLACE_ (
.CLKA(CLK2), .CLKB(CLK3),
.WREA(A1EN), .OCE(1'b0),
.WREA(|A1EN), .OCE(1'b0),
.WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
.DO({open, B1DATA}),
.ADA({A1ADDR, {(12-CFG_ABITS){1'b0}}, A1EN}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 32) begin
SDP #(
`include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(32),
.BIT_WIDTH_1(32),
.BLK_SEL(3'b000),
.RESET_MODE("SYNC")
) _TECHMAP_REPLACE_ (
.CLKA(CLK2), .CLKB(CLK3),
.WREA(|A1EN), .OCE(1'b0),
.WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
.DI(A1DATA),
.DO(B1DATA),
.ADA({A1ADDR, {(10-CFG_ABITS){1'b0}}, A1EN}),
.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else begin
wire TECHMAP_FAIL = 1'b1;

View File

@ -1,9 +1,83 @@
module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
module \$_DFF_P_ #(parameter INIT = 1'b0) (input D, C, output Q); DFF #(.INIT(INIT)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
//All DFF* have INIT, but the hardware is always initialised to the reset
//value regardless. The parameter is ignored.
// DFFN D Flip-Flop with Negative-Edge Clock
module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
// DFF D Flip-Flop
module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
// DFFE D Flip-Flop with Clock Enable
module \$_DFFE_PP_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
module \$_DFFE_PN_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
module \$_DFFE_NP_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
module \$_DFFE_NN_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
// DFFR D Flip-Flop with Synchronous Reset
module \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
module \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
module \$__DFFS_PP1_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
module \$__DFFS_NN0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
module \$__DFFS_NP0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
module \$__DFFSE_PN0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
module \$__DFFSE_PP0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
module \$__DFFNSE_PN0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
module \$__DFFNSE_PP0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
// DFFS D Flip-Flop with Synchronous Set
module \$__DFFS_PN1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
module \$__DFFS_PP1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
module \$__DFFS_NN1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
module \$__DFFS_NP1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
module \$__DFFSE_PN1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
module \$__DFFSE_PP1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
module \$__DFFSE_NN1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
module \$__DFFSE_NP1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
// DFFP D Flip-Flop with Asynchronous Preset
module \$_DFF_PP1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
module \$_DFF_PN1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
module \$_DFF_NP1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
module \$_DFF_NN1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
// DFFC D Flip-Flop with Asynchronous Clear
module \$_DFF_PP0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
module \$_DFF_PN0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
module \$_DFF_NP0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
module \$_DFF_NN0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
module \$__DFFE_PP1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
module \$__DFFE_PN1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
module \$__DFFE_NP1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
module \$__DFFE_NN1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
module \$__DFFE_PP0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
module \$__DFFE_PN0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
module \$__DFFE_NP0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
module \$__DFFE_NN0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
module \$lut (A, Y);
parameter WIDTH = 0;
@ -28,6 +102,30 @@ module \$lut (A, Y);
if (WIDTH == 4) begin
LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
end else
if (WIDTH == 5) begin
wire f0, f1;
\$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0));
\$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1));
MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y));
end else
if (WIDTH == 6) begin
wire f0, f1;
\$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0));
\$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1));
MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y));
end else
if (WIDTH == 7) begin
wire f0, f1;
\$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0));
\$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1));
MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y));
end else
if (WIDTH == 8) begin
wire f0, f1;
\$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0));
\$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1));
MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y));
end else begin
wire _TECHMAP_FAIL_ = 1;
end

View File

@ -24,6 +24,41 @@ module LUT4(output F, input I0, I1, I2, I3);
assign F = I0 ? s1[1] : s1[0];
endmodule
module MUX2 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
assign O = S0 ? I1 : I0;
endmodule
module MUX2_LUT5 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
MUX2 mux2_lut5 (O, I0, I1, S0);
endmodule
module MUX2_LUT6 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
MUX2 mux2_lut6 (O, I0, I1, S0);
endmodule
module MUX2_LUT7 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
MUX2 mux2_lut7 (O, I0, I1, S0);
endmodule
module MUX2_LUT8 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
MUX2 mux2_lut8 (O, I0, I1, S0);
endmodule
module DFF (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
@ -31,6 +66,112 @@ module DFF (output reg Q, input CLK, D);
Q <= D;
endmodule
module DFFE (output reg Q, input D, CLK, CE);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (CE)
Q <= D;
end
endmodule // DFFE (positive clock edge; clock enable)
module DFFS (output reg Q, input D, CLK, SET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (SET)
Q <= 1'b1;
else
Q <= D;
end
endmodule // DFFS (positive clock edge; synchronous set)
module DFFSE (output reg Q, input D, CLK, CE, SET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (SET)
Q <= 1'b1;
else if (CE)
Q <= D;
end
endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable)
module DFFR (output reg Q, input D, CLK, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (RESET)
Q <= 1'b0;
else
Q <= D;
end
endmodule // DFFR (positive clock edge; synchronous reset)
module DFFRE (output reg Q, input D, CLK, CE, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (RESET)
Q <= 1'b0;
else if (CE)
Q <= D;
end
endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable)
module DFFP (output reg Q, input D, CLK, PRESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
else
Q <= D;
end
endmodule // DFFP (positive clock edge; asynchronous preset)
module DFFPE (output reg Q, input D, CLK, CE, PRESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
else if (CE)
Q <= D;
end
endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable)
module DFFC (output reg Q, input D, CLK, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
else
Q <= D;
end
endmodule // DFFC (positive clock edge; asynchronous clear)
module DFFCE (output reg Q, input D, CLK, CE, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
else if (CE)
Q <= D;
end
endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable)
module DFFN (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
@ -38,16 +179,112 @@ module DFFN (output reg Q, input CLK, D);
Q <= D;
endmodule
module DFFR (output reg Q, input D, CLK, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(posedge CLK) begin
if (RESET)
Q <= 1'b0;
else
Q <= D;
end
endmodule // DFFR (positive clock edge; synchronous reset)
module DFFNE (output reg Q, input D, CLK, CE);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK) begin
if (CE)
Q <= D;
end
endmodule // DFFNE (negative clock edge; clock enable)
module DFFNS (output reg Q, input D, CLK, SET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK) begin
if (SET)
Q <= 1'b1;
else
Q <= D;
end
endmodule // DFFNS (negative clock edge; synchronous set)
module DFFNSE (output reg Q, input D, CLK, CE, SET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK) begin
if (SET)
Q <= 1'b1;
else if (CE)
Q <= D;
end
endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable)
module DFFNR (output reg Q, input D, CLK, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK) begin
if (RESET)
Q <= 1'b0;
else
Q <= D;
end
endmodule // DFFNR (negative clock edge; synchronous reset)
module DFFNRE (output reg Q, input D, CLK, CE, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK) begin
if (RESET)
Q <= 1'b0;
else if (CE)
Q <= D;
end
endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable)
module DFFNP (output reg Q, input D, CLK, PRESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
else
Q <= D;
end
endmodule // DFFNP (negative clock edge; asynchronous preset)
module DFFNPE (output reg Q, input D, CLK, CE, PRESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
else if (CE)
Q <= D;
end
endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable)
module DFFNC (output reg Q, input D, CLK, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
else
Q <= D;
end
endmodule // DFFNC (negative clock edge; asynchronous clear)
module DFFNCE (output reg Q, input D, CLK, CE, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
always @(negedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
else if (CE)
Q <= D;
end
endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable)
// TODO add more DFF sim cells
module VCC(output V);
assign V = 1;
@ -65,14 +302,98 @@ module OBUF(output O, input I);
assign O = I;
endmodule
module TBUF (O, I, OEN);
input I, OEN;
output O;
assign O = OEN ? I : 1'bz;
endmodule
module IOBUF (O, IO, I, OEN);
input I,OEN;
output O;
inout IO;
assign IO = OEN ? I : 1'bz;
assign I = IO;
endmodule
module GSR (input GSRI);
wire GSRO = GSRI;
endmodule
module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM);
parameter [3:0] ALU_MODE = 0; // default 0 = ADD
assign {COUT, SUM} = CIN + I1 + I0;
endmodule // alu
module ALU (SUM, COUT, I0, I1, I3, CIN);
input I0;
input I1;
input I3;
input CIN;
output SUM;
output COUT;
localparam ADD = 0;
localparam SUB = 1;
localparam ADDSUB = 2;
localparam NE = 3;
localparam GE = 4;
localparam LE = 5;
localparam CUP = 6;
localparam CDN = 7;
localparam CUPCDN = 8;
localparam MULT = 9;
parameter ALU_MODE = 0;
reg S, C;
assign SUM = S ^ CIN;
assign COUT = S? CIN : C;
always @* begin
case (ALU_MODE)
ADD: begin
S = I0 ^ I1;
C = I0;
end
SUB: begin
S = I0 ^ ~I1;
C = I0;
end
ADDSUB: begin
S = I3? I0 ^ I1 : I0 ^ ~I1;
C = I0;
end
NE: begin
S = I0 ^ ~I1;
C = 1'b1;
end
GE: begin
S = I0 ^ ~I1;
C = I0;
end
LE: begin
S = ~I0 ^ I1;
C = I1;
end
CUP: begin
S = I0;
C = 1'b0;
end
CDN: begin
S = ~I0;
C = 1'b1;
end
CUPCDN: begin
S = I3? I0 : ~I0;
C = I0;
end
MULT: begin
S = I0 & I1;
C = I0 & I1;
end
endcase
end
endmodule
module RAM16S4 (DO, DI, AD, WRE, CLK);
parameter WIDTH = 4;

View File

@ -64,6 +64,12 @@ struct SynthGowinPass : public ScriptPass
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
log(" -nowidelut\n");
log(" do not use muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
@ -71,7 +77,7 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
bool retime, nobram, nodram, flatten, nodffe;
bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9;
void clear_flags() YS_OVERRIDE
{
@ -82,6 +88,8 @@ struct SynthGowinPass : public ScriptPass
nobram = false;
nodffe = false;
nodram = false;
nowidelut = false;
abc9 = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@ -128,6 +136,14 @@ struct SynthGowinPass : public ScriptPass
flatten = false;
continue;
}
if (args[argidx] == "-nowidelut") {
nowidelut = true;
continue;
}
if (args[argidx] == "-abc9") {
abc9 = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -163,8 +179,8 @@ struct SynthGowinPass : public ScriptPass
{
run("synth -run coarse");
}
if (!nobram && check_label("bram", "(skip if -nobram)"))
if (!nobram && check_label("bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/gowin/bram.txt");
run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v");
@ -186,6 +202,7 @@ struct SynthGowinPass : public ScriptPass
run("techmap -map +/techmap.v");
if (retime || help_mode)
run("abc -dff", "(only if -retime)");
run("splitnets");
}
if (check_label("map_ffs"))
@ -202,16 +219,25 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_luts"))
{
run("abc -lut 4");
if (nowidelut && abc9) {
run("abc9 -lut 4");
} else if (nowidelut && !abc9) {
run("abc -lut 4");
} else if (!nowidelut && abc9) {
run("abc9 -lut 4:8");
} else if (!nowidelut && !abc9) {
run("abc -lut 4:8");
}
run("clean");
}
if (check_label("map_cells"))
{
run("techmap -map +/gowin/cells_map.v");
run("hilomap -hicell VCC V -locell GND G");
run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O", "(unless -noiopads)");
run("dffinit -ff DFF Q INIT");
run("setundef -undriven -params -zero");
run("hilomap -singleton -hicell VCC V -locell GND G");
run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
"-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");
run("clean");
}
@ -226,7 +252,7 @@ struct SynthGowinPass : public ScriptPass
if (check_label("vout"))
{
if (!vout_file.empty() || help_mode)
run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix gen %s",
run(stringf("write_verilog -decimal -attr2comment -defparam -renameprefix gen %s",
help_mode ? "<file-name>" : vout_file.c_str()));
}
}

View File

@ -14,7 +14,7 @@ EXTRA_OBJS += techlibs/ice40/brams_init.mk
techlibs/ice40/brams_init.mk: techlibs/ice40/brams_init.py
$(Q) mkdir -p techlibs/ice40
$(P) python3 $<
$(P) $(PYTHON_EXECUTABLE) $<
$(Q) touch techlibs/ice40/brams_init.mk
techlibs/ice40/brams_init1.vh: techlibs/ice40/brams_init.mk

View File

@ -1,4 +1,4 @@
`timescale 1ps / 1ps
`define SB_DFF_REG reg Q = 0
// `define SB_DFF_REG reg Q
@ -81,6 +81,37 @@ module SB_IO (
if (PIN_TYPE[5:4] == 2'b11) assign PACKAGE_PIN = outena_q ? dout : 1'bz;
endgenerate
`endif
`ifdef TIMING
specify
(INPUT_CLK => D_IN_0) = (0:0:0, 0:0:0);
(INPUT_CLK => D_IN_1) = (0:0:0, 0:0:0);
(PACKAGE_PIN => D_IN_0) = (0:0:0, 0:0:0);
(OUTPUT_CLK => PACKAGE_PIN) = (0:0:0, 0:0:0);
(D_OUT_0 => PACKAGE_PIN) = (0:0:0, 0:0:0);
(OUTPUT_ENABLE => PACKAGE_PIN) = (0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, posedge D_OUT_0, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, negedge D_OUT_0, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, posedge D_OUT_1, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, negedge D_OUT_1, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, posedge D_OUT_0, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, negedge D_OUT_0, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, posedge D_OUT_1, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, negedge D_OUT_1, 0:0:0, 0:0:0);
$setuphold(posedge INPUT_CLK, posedge CLOCK_ENABLE, 0:0:0, 0:0:0);
$setuphold(posedge INPUT_CLK, negedge CLOCK_ENABLE, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, posedge CLOCK_ENABLE, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, negedge CLOCK_ENABLE, 0:0:0, 0:0:0);
$setuphold(posedge INPUT_CLK, posedge PACKAGE_PIN, 0:0:0, 0:0:0);
$setuphold(posedge INPUT_CLK, negedge PACKAGE_PIN, 0:0:0, 0:0:0);
$setuphold(negedge INPUT_CLK, posedge PACKAGE_PIN, 0:0:0, 0:0:0);
$setuphold(negedge INPUT_CLK, negedge PACKAGE_PIN, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, posedge OUTPUT_ENABLE, 0:0:0, 0:0:0);
$setuphold(posedge OUTPUT_CLK, negedge OUTPUT_ENABLE, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, posedge OUTPUT_ENABLE, 0:0:0, 0:0:0);
$setuphold(negedge OUTPUT_CLK, negedge OUTPUT_ENABLE, 0:0:0, 0:0:0);
endspecify
`endif
endmodule
module SB_GB_IO (
@ -127,6 +158,11 @@ module SB_GB (
output GLOBAL_BUFFER_OUTPUT
);
assign GLOBAL_BUFFER_OUTPUT = USER_SIGNAL_TO_GLOBAL_BUFFER;
`ifdef TIMING
specify
(USER_SIGNAL_TO_GLOBAL_BUFFER => GLOBAL_BUFFER_OUTPUT) = (0:0:0, 0:0:0);
endspecify
`endif
endmodule
// SiliconBlue Logic Cells
@ -830,33 +866,81 @@ module ICESTORM_LC (
parameter [0:0] CIN_CONST = 0;
parameter [0:0] CIN_SET = 0;
wire I0_pd = (I0 === 1'bz) ? 1'b0 : I0;
wire I1_pd = (I1 === 1'bz) ? 1'b0 : I1;
wire I2_pd = (I2 === 1'bz) ? 1'b0 : I2;
wire I3_pd = (I3 === 1'bz) ? 1'b0 : I3;
wire SR_pd = (SR === 1'bz) ? 1'b0 : SR;
wire CEN_pu = (CEN === 1'bz) ? 1'b1 : CEN;
wire mux_cin = CIN_CONST ? CIN_SET : CIN;
assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && mux_cin) : 1'bx;
assign COUT = CARRY_ENABLE ? (I1_pd && I2_pd) || ((I1_pd || I2_pd) && mux_cin) : 1'bx;
wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] lut_s2 = I2 ? lut_s3[ 7:4] : lut_s3[3:0];
wire [1:0] lut_s1 = I1 ? lut_s2[ 3:2] : lut_s2[1:0];
wire lut_o = I0 ? lut_s1[ 1] : lut_s1[ 0];
wire [7:0] lut_s3 = I3_pd ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] lut_s2 = I2_pd ? lut_s3[ 7:4] : lut_s3[3:0];
wire [1:0] lut_s1 = I1_pd ? lut_s2[ 3:2] : lut_s2[1:0];
wire lut_o = I0_pd ? lut_s1[ 1] : lut_s1[ 0];
assign LO = lut_o;
wire polarized_clk;
assign polarized_clk = CLK ^ NEG_CLK;
reg o_reg;
reg o_reg = 1'b0;
always @(posedge polarized_clk)
if (CEN)
o_reg <= SR ? SET_NORESET : lut_o;
if (CEN_pu)
o_reg <= SR_pd ? SET_NORESET : lut_o;
reg o_reg_async;
reg o_reg_async = 1'b0;
always @(posedge polarized_clk, posedge SR)
if (SR)
o_reg <= SET_NORESET;
else if (CEN)
o_reg <= lut_o;
if (SR_pd)
o_reg_async <= SET_NORESET;
else if (CEN_pu)
o_reg_async <= lut_o;
assign O = DFF_ENABLE ? ASYNC_SR ? o_reg_async : o_reg : lut_o;
`ifdef TIMING
specify
(I0 => O) = (0:0:0, 0:0:0);
(I1 => O) = (0:0:0, 0:0:0);
(I2 => O) = (0:0:0, 0:0:0);
(I3 => O) = (0:0:0, 0:0:0);
(I0 => LO) = (0:0:0, 0:0:0);
(I1 => LO) = (0:0:0, 0:0:0);
(I2 => LO) = (0:0:0, 0:0:0);
(I3 => LO) = (0:0:0, 0:0:0);
(I1 => COUT) = (0:0:0, 0:0:0);
(I2 => COUT) = (0:0:0, 0:0:0);
(CIN => COUT) = (0:0:0, 0:0:0);
(CLK => O) = (0:0:0, 0:0:0);
(SR => O) = (0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge I0, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge I0, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge I0, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge I0, 0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge I1, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge I1, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge I1, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge I1, 0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge I2, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge I2, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge I2, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge I2, 0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge I3, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge I3, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge I3, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge I3, 0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge CEN, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge CEN, 0:0:0, 0:0:0);
$setuphold(posedge CLK, posedge SR, 0:0:0, 0:0:0);
$setuphold(posedge CLK, negedge SR, 0:0:0, 0:0:0);
$setuphold(negedge CLK, posedge SR, 0:0:0, 0:0:0);
$setuphold(negedge CLK, negedge SR, 0:0:0, 0:0:0);
endspecify
`endif
endmodule
// SiliconBlue PLL Cells
@ -1576,3 +1660,341 @@ module SB_MAC16 (
assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI;
assign O = {Oh, Ol};
endmodule
// Post-place-and-route RAM model
module ICESTORM_RAM(
output RDATA_15, RDATA_14, RDATA_13, RDATA_12, RDATA_11, RDATA_10, RDATA_9, RDATA_8, RDATA_7, RDATA_6, RDATA_5, RDATA_4, RDATA_3, RDATA_2, RDATA_1, RDATA_0,
input RCLK, RCLKE, RE,
input RADDR_10, RADDR_9, RADDR_8, RADDR_7, RADDR_6, RADDR_5, RADDR_4, RADDR_3, RADDR_2, RADDR_1, RADDR_0,
input WCLK, WCLKE, WE,
input WADDR_10, WADDR_9, WADDR_8, WADDR_7, WADDR_6, WADDR_5, WADDR_4, WADDR_3, WADDR_2, WADDR_1, WADDR_0,
input MASK_15, MASK_14, MASK_13, MASK_12, MASK_11, MASK_10, MASK_9, MASK_8, MASK_7, MASK_6, MASK_5, MASK_4, MASK_3, MASK_2, MASK_1, MASK_0,
input WDATA_15, WDATA_14, WDATA_13, WDATA_12, WDATA_11, WDATA_10, WDATA_9, WDATA_8, WDATA_7, WDATA_6, WDATA_5, WDATA_4, WDATA_3, WDATA_2, WDATA_1, WDATA_0
);
parameter WRITE_MODE = 0;
parameter READ_MODE = 0;
parameter NEG_CLK_R = 1'b0;
parameter NEG_CLK_W = 1'b0;
parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
// Pull-down and pull-up functions
function pd;
input x;
begin
pd = (x === 1'bz) ? 1'b0 : x;
end
endfunction
function pu;
input x;
begin
pu = (x === 1'bz) ? 1'b1 : x;
end
endfunction
SB_RAM40_4K #(
.WRITE_MODE(WRITE_MODE),
.READ_MODE (READ_MODE ),
.INIT_0 (INIT_0 ),
.INIT_1 (INIT_1 ),
.INIT_2 (INIT_2 ),
.INIT_3 (INIT_3 ),
.INIT_4 (INIT_4 ),
.INIT_5 (INIT_5 ),
.INIT_6 (INIT_6 ),
.INIT_7 (INIT_7 ),
.INIT_8 (INIT_8 ),
.INIT_9 (INIT_9 ),
.INIT_A (INIT_A ),
.INIT_B (INIT_B ),
.INIT_C (INIT_C ),
.INIT_D (INIT_D ),
.INIT_E (INIT_E ),
.INIT_F (INIT_F )
) RAM (
.RDATA({RDATA_15, RDATA_14, RDATA_13, RDATA_12, RDATA_11, RDATA_10, RDATA_9, RDATA_8, RDATA_7, RDATA_6, RDATA_5, RDATA_4, RDATA_3, RDATA_2, RDATA_1, RDATA_0}),
.RCLK (pd(RCLK) ^ NEG_CLK_R),
.RCLKE(pu(RCLKE)),
.RE (pd(RE)),
.RADDR({pd(RADDR_10), pd(RADDR_9), pd(RADDR_8), pd(RADDR_7), pd(RADDR_6), pd(RADDR_5), pd(RADDR_4), pd(RADDR_3), pd(RADDR_2), pd(RADDR_1), pd(RADDR_0)}),
.WCLK (pd(WCLK) ^ NEG_CLK_W),
.WCLKE(pu(WCLKE)),
.WE (pd(WE)),
.WADDR({pd(WADDR_10), pd(WADDR_9), pd(WADDR_8), pd(WADDR_7), pd(WADDR_6), pd(WADDR_5), pd(WADDR_4), pd(WADDR_3), pd(WADDR_2), pd(WADDR_1), pd(WADDR_0)}),
.MASK ({pd(MASK_15), pd(MASK_14), pd(MASK_13), pd(MASK_12), pd(MASK_11), pd(MASK_10), pd(MASK_9), pd(MASK_8),
pd(MASK_7), pd(MASK_6), pd(MASK_5), pd(MASK_4), pd(MASK_3), pd(MASK_2), pd(MASK_1), pd(MASK_0)}),
.WDATA({pd(WDATA_15), pd(WDATA_14), pd(WDATA_13), pd(WDATA_12), pd(WDATA_11), pd(WDATA_10), pd(WDATA_9), pd(WDATA_8),
pd(WDATA_7), pd(WDATA_6), pd(WDATA_5), pd(WDATA_4), pd(WDATA_3), pd(WDATA_2), pd(WDATA_1), pd(WDATA_0)})
);
`ifdef TIMING
specify
(RCLK => RDATA_15) = (0:0:0, 0:0:0);
(RCLK => RDATA_14) = (0:0:0, 0:0:0);
(RCLK => RDATA_13) = (0:0:0, 0:0:0);
(RCLK => RDATA_12) = (0:0:0, 0:0:0);
(RCLK => RDATA_11) = (0:0:0, 0:0:0);
(RCLK => RDATA_10) = (0:0:0, 0:0:0);
(RCLK => RDATA_9) = (0:0:0, 0:0:0);
(RCLK => RDATA_8) = (0:0:0, 0:0:0);
(RCLK => RDATA_7) = (0:0:0, 0:0:0);
(RCLK => RDATA_6) = (0:0:0, 0:0:0);
(RCLK => RDATA_5) = (0:0:0, 0:0:0);
(RCLK => RDATA_4) = (0:0:0, 0:0:0);
(RCLK => RDATA_3) = (0:0:0, 0:0:0);
(RCLK => RDATA_2) = (0:0:0, 0:0:0);
(RCLK => RDATA_1) = (0:0:0, 0:0:0);
(RCLK => RDATA_0) = (0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RCLKE, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RCLKE, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RCLKE, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RCLKE, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RE, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RE, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RE, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RE, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_10, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_10, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_10, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_10, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_9, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_9, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_9, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_9, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_8, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_8, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_8, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_8, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_7, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_7, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_7, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_7, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_6, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_6, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_6, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_6, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_5, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_5, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_5, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_5, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_4, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_4, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_4, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_4, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_3, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_3, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_3, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_3, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_2, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_2, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_2, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_2, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_1, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_1, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_1, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_1, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, posedge RADDR_0, 0:0:0, 0:0:0);
$setuphold(posedge RCLK, negedge RADDR_0, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, posedge RADDR_0, 0:0:0, 0:0:0);
$setuphold(negedge RCLK, negedge RADDR_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WCLKE, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WCLKE, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WCLKE, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WCLKE, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WE, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WE, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WE, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WE, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WADDR_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WADDR_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WADDR_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WADDR_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_15, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_15, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_15, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_15, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_14, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_14, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_14, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_14, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_13, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_13, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_13, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_13, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_12, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_12, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_12, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_12, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_11, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_11, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_11, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_11, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge MASK_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge MASK_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge MASK_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge MASK_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_15, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_15, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_15, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_15, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_14, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_14, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_14, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_14, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_13, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_13, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_13, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_13, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_12, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_12, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_12, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_12, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_11, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_11, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_11, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_11, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_10, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_10, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_9, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_9, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_8, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_8, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_7, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_7, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_6, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_6, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_5, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_5, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_4, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_4, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_3, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_3, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_2, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_2, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_1, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_1, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, posedge WDATA_0, 0:0:0, 0:0:0);
$setuphold(posedge WCLK, negedge WDATA_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, posedge WDATA_0, 0:0:0, 0:0:0);
$setuphold(negedge WCLK, negedge WDATA_0, 0:0:0, 0:0:0);
endspecify
`endif
endmodule

View File

@ -273,6 +273,7 @@ struct SynthIce40Pass : public ScriptPass
run("opt_expr");
run("opt_clean");
if (help_mode || dsp) {
run("memory_dff");
run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 "
"-D DSP_NAME=$__MUL16X16", "(if -dsp)");
@ -379,6 +380,7 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");

View File

@ -13,7 +13,7 @@ EXTRA_OBJS += techlibs/xilinx/brams_init.mk
techlibs/xilinx/brams_init.mk: techlibs/xilinx/brams_init.py
$(Q) mkdir -p techlibs/xilinx
$(P) python3 $<
$(P) $(PYTHON_EXECUTABLE) $<
$(Q) touch $@
techlibs/xilinx/brams_init_36.vh: techlibs/xilinx/brams_init.mk
@ -25,16 +25,14 @@ techlibs/xilinx/brams_init_8.vh: techlibs/xilinx/brams_init.mk
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_cells_xtra.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6v_cells_xtra.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_cells_xtra.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_cells_xtra.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_xtra.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_bb.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_xcu_brams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_brams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
@ -42,7 +40,13 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3s_mult_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3sda_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc4v_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v))

View File

@ -38,6 +38,17 @@ module IBUF(
assign O = I;
endmodule
module IBUFG(
output O,
(* iopad_external_pin *)
input I);
parameter CAPACITANCE = "DONT_CARE";
parameter IBUF_DELAY_VALUE = "0";
parameter IBUF_LOW_PWR = "TRUE";
parameter IOSTANDARD = "DEFAULT";
assign O = I;
endmodule
module OBUF(
(* iopad_external_pin *)
output O,
@ -578,6 +589,515 @@ module SRLC32E (
endgenerate
endmodule
// DSP
// Virtex 2, Virtex 2 Pro, Spartan 3.
// Asynchronous mode.
module MULT18X18 (
input signed [17:0] A,
input signed [17:0] B,
output signed [35:0] P
);
assign P = A * B;
endmodule
// Synchronous mode.
module MULT18X18S (
input signed [17:0] A,
input signed [17:0] B,
output reg signed [35:0] P,
(* clkbuf_sink *)
input C,
input CE,
input R
);
always @(posedge C)
if (R)
P <= 0;
else if (CE)
P <= A * B;
endmodule
// Spartan 3E, Spartan 3A.
module MULT18X18SIO (
input signed [17:0] A,
input signed [17:0] B,
output signed [35:0] P,
(* clkbuf_sink *)
input CLK,
input CEA,
input CEB,
input CEP,
input RSTA,
input RSTB,
input RSTP,
input signed [17:0] BCIN,
output signed [17:0] BCOUT
);
parameter integer AREG = 1;
parameter integer BREG = 1;
parameter B_INPUT = "DIRECT";
parameter integer PREG = 1;
// The multiplier.
wire signed [35:0] P_MULT;
assign P_MULT = A_MULT * B_MULT;
// The cascade output.
assign BCOUT = B_MULT;
// The B input multiplexer.
wire signed [17:0] B_MUX;
assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN;
// The registers.
reg signed [17:0] A_REG;
reg signed [17:0] B_REG;
reg signed [35:0] P_REG;
initial begin
A_REG = 0;
B_REG = 0;
P_REG = 0;
end
always @(posedge CLK) begin
if (RSTA)
A_REG <= 0;
else if (CEA)
A_REG <= A;
if (RSTB)
B_REG <= 0;
else if (CEB)
B_REG <= B_MUX;
if (RSTP)
P_REG <= 0;
else if (CEP)
P_REG <= P_MULT;
end
// The register enables.
wire signed [17:0] A_MULT;
wire signed [17:0] B_MULT;
assign A_MULT = (AREG == 1) ? A_REG : A;
assign B_MULT = (BREG == 1) ? B_REG : B_MUX;
assign P = (PREG == 1) ? P_REG : P_MULT;
endmodule
// Spartan 3A DSP.
module DSP48A (
input signed [17:0] A,
input signed [17:0] B,
input signed [47:0] C,
input signed [17:0] D,
input signed [47:0] PCIN,
input CARRYIN,
input [7:0] OPMODE,
output signed [47:0] P,
output signed [17:0] BCOUT,
output signed [47:0] PCOUT,
output CARRYOUT,
(* clkbuf_sink *)
input CLK,
input CEA,
input CEB,
input CEC,
input CED,
input CEM,
input CECARRYIN,
input CEOPMODE,
input CEP,
input RSTA,
input RSTB,
input RSTC,
input RSTD,
input RSTM,
input RSTCARRYIN,
input RSTOPMODE,
input RSTP
);
parameter integer A0REG = 0;
parameter integer A1REG = 1;
parameter integer B0REG = 0;
parameter integer B1REG = 1;
parameter integer CREG = 1;
parameter integer DREG = 1;
parameter integer MREG = 1;
parameter integer CARRYINREG = 1;
parameter integer OPMODEREG = 1;
parameter integer PREG = 1;
parameter CARRYINSEL = "CARRYIN";
parameter RSTTYPE = "SYNC";
// This is a strict subset of Spartan 6 -- reuse its model.
DSP48A1 #(
.A0REG(A0REG),
.A1REG(A1REG),
.B0REG(B0REG),
.B1REG(B1REG),
.CREG(CREG),
.DREG(DREG),
.MREG(MREG),
.CARRYINREG(CARRYINREG),
.CARRYOUTREG(0),
.OPMODEREG(OPMODEREG),
.PREG(PREG),
.CARRYINSEL(CARRYINSEL),
.RSTTYPE(RSTTYPE)
) upgrade (
.A(A),
.B(B),
.C(C),
.D(D),
.PCIN(PCIN),
.CARRYIN(CARRYIN),
.OPMODE(OPMODE),
// M unconnected
.P(P),
.BCOUT(BCOUT),
.PCOUT(PCOUT),
.CARRYOUT(CARRYOUT),
// CARRYOUTF unconnected
.CLK(CLK),
.CEA(CEA),
.CEB(CEB),
.CEC(CEC),
.CED(CED),
.CEM(CEM),
.CECARRYIN(CECARRYIN),
.CEOPMODE(CEOPMODE),
.CEP(CEP),
.RSTA(RSTA),
.RSTB(RSTB),
.RSTC(RSTC),
.RSTD(RSTD),
.RSTM(RSTM),
.RSTCARRYIN(RSTCARRYIN),
.RSTOPMODE(RSTOPMODE),
.RSTP(RSTP)
);
endmodule
// Spartan 6.
module DSP48A1 (
input signed [17:0] A,
input signed [17:0] B,
input signed [47:0] C,
input signed [17:0] D,
input signed [47:0] PCIN,
input CARRYIN,
input [7:0] OPMODE,
output signed [35:0] M,
output signed [47:0] P,
output signed [17:0] BCOUT,
output signed [47:0] PCOUT,
output CARRYOUT,
output CARRYOUTF,
(* clkbuf_sink *)
input CLK,
input CEA,
input CEB,
input CEC,
input CED,
input CEM,
input CECARRYIN,
input CEOPMODE,
input CEP,
input RSTA,
input RSTB,
input RSTC,
input RSTD,
input RSTM,
input RSTCARRYIN,
input RSTOPMODE,
input RSTP
);
parameter integer A0REG = 0;
parameter integer A1REG = 1;
parameter integer B0REG = 0;
parameter integer B1REG = 1;
parameter integer CREG = 1;
parameter integer DREG = 1;
parameter integer MREG = 1;
parameter integer CARRYINREG = 1;
parameter integer CARRYOUTREG = 1;
parameter integer OPMODEREG = 1;
parameter integer PREG = 1;
parameter CARRYINSEL = "OPMODE5";
parameter RSTTYPE = "SYNC";
wire signed [35:0] M_MULT;
wire signed [47:0] P_IN;
wire signed [17:0] A0_OUT;
wire signed [17:0] B0_OUT;
wire signed [17:0] A1_OUT;
wire signed [17:0] B1_OUT;
wire signed [17:0] B1_IN;
wire signed [47:0] C_OUT;
wire signed [17:0] D_OUT;
wire signed [7:0] OPMODE_OUT;
wire CARRYIN_OUT;
wire CARRYOUT_IN;
wire CARRYIN_IN;
reg signed [47:0] XMUX;
reg signed [47:0] ZMUX;
// The registers.
reg signed [17:0] A0_REG;
reg signed [17:0] A1_REG;
reg signed [17:0] B0_REG;
reg signed [17:0] B1_REG;
reg signed [47:0] C_REG;
reg signed [17:0] D_REG;
reg signed [35:0] M_REG;
reg signed [47:0] P_REG;
reg [7:0] OPMODE_REG;
reg CARRYIN_REG;
reg CARRYOUT_REG;
initial begin
A0_REG = 0;
A1_REG = 0;
B0_REG = 0;
B1_REG = 0;
C_REG = 0;
D_REG = 0;
M_REG = 0;
P_REG = 0;
OPMODE_REG = 0;
CARRYIN_REG = 0;
CARRYOUT_REG = 0;
end
generate
if (RSTTYPE == "SYNC") begin
always @(posedge CLK) begin
if (RSTA) begin
A0_REG <= 0;
A1_REG <= 0;
end else if (CEA) begin
A0_REG <= A;
A1_REG <= A0_OUT;
end
end
always @(posedge CLK) begin
if (RSTB) begin
B0_REG <= 0;
B1_REG <= 0;
end else if (CEB) begin
B0_REG <= B;
B1_REG <= B1_IN;
end
end
always @(posedge CLK) begin
if (RSTC) begin
C_REG <= 0;
end else if (CEC) begin
C_REG <= C;
end
end
always @(posedge CLK) begin
if (RSTD) begin
D_REG <= 0;
end else if (CED) begin
D_REG <= D;
end
end
always @(posedge CLK) begin
if (RSTM) begin
M_REG <= 0;
end else if (CEM) begin
M_REG <= M_MULT;
end
end
always @(posedge CLK) begin
if (RSTP) begin
P_REG <= 0;
end else if (CEP) begin
P_REG <= P_IN;
end
end
always @(posedge CLK) begin
if (RSTOPMODE) begin
OPMODE_REG <= 0;
end else if (CEOPMODE) begin
OPMODE_REG <= OPMODE;
end
end
always @(posedge CLK) begin
if (RSTCARRYIN) begin
CARRYIN_REG <= 0;
CARRYOUT_REG <= 0;
end else if (CECARRYIN) begin
CARRYIN_REG <= CARRYIN_IN;
CARRYOUT_REG <= CARRYOUT_IN;
end
end
end else begin
always @(posedge CLK, posedge RSTA) begin
if (RSTA) begin
A0_REG <= 0;
A1_REG <= 0;
end else if (CEA) begin
A0_REG <= A;
A1_REG <= A0_OUT;
end
end
always @(posedge CLK, posedge RSTB) begin
if (RSTB) begin
B0_REG <= 0;
B1_REG <= 0;
end else if (CEB) begin
B0_REG <= B;
B1_REG <= B1_IN;
end
end
always @(posedge CLK, posedge RSTC) begin
if (RSTC) begin
C_REG <= 0;
end else if (CEC) begin
C_REG <= C;
end
end
always @(posedge CLK, posedge RSTD) begin
if (RSTD) begin
D_REG <= 0;
end else if (CED) begin
D_REG <= D;
end
end
always @(posedge CLK, posedge RSTM) begin
if (RSTM) begin
M_REG <= 0;
end else if (CEM) begin
M_REG <= M_MULT;
end
end
always @(posedge CLK, posedge RSTP) begin
if (RSTP) begin
P_REG <= 0;
end else if (CEP) begin
P_REG <= P_IN;
end
end
always @(posedge CLK, posedge RSTOPMODE) begin
if (RSTOPMODE) begin
OPMODE_REG <= 0;
end else if (CEOPMODE) begin
OPMODE_REG <= OPMODE;
end
end
always @(posedge CLK, posedge RSTCARRYIN) begin
if (RSTCARRYIN) begin
CARRYIN_REG <= 0;
CARRYOUT_REG <= 0;
end else if (CECARRYIN) begin
CARRYIN_REG <= CARRYIN_IN;
CARRYOUT_REG <= CARRYOUT_IN;
end
end
end
endgenerate
// The register enables.
assign A0_OUT = (A0REG == 1) ? A0_REG : A;
assign A1_OUT = (A1REG == 1) ? A1_REG : A0_OUT;
assign B0_OUT = (B0REG == 1) ? B0_REG : B;
assign B1_OUT = (B1REG == 1) ? B1_REG : B1_IN;
assign C_OUT = (CREG == 1) ? C_REG : C;
assign D_OUT = (DREG == 1) ? D_REG : D;
assign M = (MREG == 1) ? M_REG : M_MULT;
assign P = (PREG == 1) ? P_REG : P_IN;
assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE;
assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN_IN;
assign CARRYOUT = (CARRYOUTREG == 1) ? CARRYOUT_REG : CARRYOUT_IN;
assign CARRYOUTF = CARRYOUT;
// The pre-adder.
wire signed [17:0] PREADDER;
assign B1_IN = OPMODE_OUT[4] ? PREADDER : B0_OUT;
assign PREADDER = OPMODE_OUT[6] ? D_OUT - B0_OUT : D_OUT + B0_OUT;
// The multiplier.
assign M_MULT = A1_OUT * B1_OUT;
// The carry in selection.
assign CARRYIN_IN = (CARRYINSEL == "OPMODE5") ? OPMODE_OUT[5] : CARRYIN;
// The post-adder inputs.
always @* begin
case (OPMODE_OUT[1:0])
2'b00: XMUX <= 0;
2'b01: XMUX <= M;
2'b10: XMUX <= P;
2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT};
default: XMUX <= 48'hxxxxxxxxxxxx;
endcase
end
always @* begin
case (OPMODE_OUT[3:2])
2'b00: ZMUX <= 0;
2'b01: ZMUX <= PCIN;
2'b10: ZMUX <= P;
2'b11: ZMUX <= C_OUT;
default: ZMUX <= 48'hxxxxxxxxxxxx;
endcase
end
// The post-adder.
wire signed [48:0] X_EXT;
wire signed [48:0] Z_EXT;
assign X_EXT = XMUX;
assign Z_EXT = ZMUX;
assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT);
// Cascade outputs.
assign BCOUT = B1_OUT;
assign PCOUT = P;
endmodule
// TODO: DSP48 (Virtex 4).
// TODO: DSP48E (Virtex 5).
// Virtex 6, Series 7.
module DSP48E1 (
output [29:0] ACOUT,
output [17:0] BCOUT,
@ -1040,3 +1560,5 @@ module DSP48E1 (
endgenerate
endmodule
// TODO: DSP48E2 (Ultrascale).

File diff suppressed because it is too large Load Diff

29212
techlibs/xilinx/cells_xtra.v Normal file

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ struct SynthXilinxPass : public ScriptPass
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -family {xcup|xcu|xc7|xc6v|xc6s}\n");
log(" -family {xcup|xcu|xc7|xc6v|xc5v|xc6s}\n");
log(" run synthesis for the specified Xilinx architecture\n");
log(" generate the synthesis netlist for the specified family.\n");
log(" default: xc7\n");
@ -93,6 +93,9 @@ struct SynthXilinxPass : public ScriptPass
log(" -noclkbuf\n");
log(" disable automatic clock buffer insertion\n");
log("\n");
log(" -uram\n");
log(" infer URAM288s for large memories (xcup only)\n");
log("\n");
log(" -widemux <int>\n");
log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
log(" above this number of inputs (minimum value 2, recommended value >= 5).\n");
@ -119,7 +122,7 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9;
bool flatten_before_abc;
int widemux;
@ -143,6 +146,7 @@ struct SynthXilinxPass : public ScriptPass
nocarry = false;
nowidelut = false;
nodsp = false;
uram = false;
abc9 = false;
flatten_before_abc = false;
widemux = 0;
@ -248,11 +252,15 @@ struct SynthXilinxPass : public ScriptPass
nodsp = true;
continue;
}
if (args[argidx] == "-uram") {
uram = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc6s")
if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc5v" && family != "xc6s")
log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str());
if (widemux != 0 && widemux < 2)
@ -289,24 +297,7 @@ struct SynthXilinxPass : public ScriptPass
read_args += " -lib +/xilinx/cells_sim.v";
run("read_verilog" + read_args);
if (help_mode)
run("read_verilog -lib +/xilinx/{family}_cells_xtra.v");
else if (family == "xc6s")
run("read_verilog -lib +/xilinx/xc6s_cells_xtra.v");
else if (family == "xc6v")
run("read_verilog -lib +/xilinx/xc6v_cells_xtra.v");
else if (family == "xc7")
run("read_verilog -lib +/xilinx/xc7_cells_xtra.v");
else if (family == "xcu" || family == "xcup")
run("read_verilog -lib +/xilinx/xcu_cells_xtra.v");
if (help_mode) {
run("read_verilog -lib +/xilinx/{family}_brams_bb.v");
} else if (family == "xc6s") {
run("read_verilog -lib +/xilinx/xc6s_brams_bb.v");
} else if (family == "xc6v" || family == "xc7") {
run("read_verilog -lib +/xilinx/xc7_brams_bb.v");
}
run("read_verilog -lib +/xilinx/cells_xtra.v");
run(stringf("hierarchy -check %s", top_opt.c_str()));
}
@ -342,15 +333,53 @@ struct SynthXilinxPass : public ScriptPass
if (check_label("map_dsp", "(skip if '-nodsp')")) {
if (!nodsp || help_mode) {
run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first
// NB: Xilinx multipliers are signed only
run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
if (help_mode)
run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}");
else if (family == "xc2v" || family == "xc3s" || family == "xc3se" || family == "xc3sa")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc3sda")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc3sda_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc6s")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc6s_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc4v")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc4v_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc5v")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc5v_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
else if (family == "xc6v" || family == "xc7")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc7_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
else if (family == "xcu" || family == "xcup")
run("techmap -map +/mul2dsp.v -map +/xilinx/xcu_dsp_map.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL27X18");
run("select a:mul2dsp");
run("setattr -unset mul2dsp");
run("opt_expr -fine");
@ -371,6 +400,20 @@ struct SynthXilinxPass : public ScriptPass
run("opt_clean");
}
if (check_label("map_uram", "(only if '-uram')")) {
if (help_mode) {
run("memory_bram -rules +/xilinx/{family}_urams.txt");
run("techmap -map +/xilinx/{family}_urams_map.v");
} else if (uram) {
if (family == "xcup") {
run("memory_bram -rules +/xilinx/xcup_urams.txt");
run("techmap -map +/xilinx/xcup_urams_map.v");
} else {
log_warning("UltraRAM inference not supported for family %s.\n", family.c_str());
}
}
}
if (check_label("map_bram", "(skip if '-nobram')")) {
if (help_mode) {
run("memory_bram -rules +/xilinx/{family}_brams.txt");
@ -380,8 +423,11 @@ struct SynthXilinxPass : public ScriptPass
run("memory_bram -rules +/xilinx/xc6s_brams.txt");
run("techmap -map +/xilinx/xc6s_brams_map.v");
} else if (family == "xc6v" || family == "xc7") {
run("memory_bram -rules +/xilinx/xc7_brams.txt");
run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt");
run("techmap -map +/xilinx/xc7_brams_map.v");
} else if (family == "xcu" || family == "xcup") {
run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt");
run("techmap -map +/xilinx/xcu_brams_map.v");
} else {
log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str());
}

View File

@ -0,0 +1,14 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
MULT18X18 _TECHMAP_REPLACE_ (
.A(A),
.B(B),
.P(Y)
);
endmodule

View File

@ -0,0 +1,34 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48A #(
// Disable all registers
.A0REG(0),
.A1REG(0),
.B0REG(0),
.B1REG(0),
.CARRYINREG(0),
.CARRYINSEL("OPMODE5"),
.CREG(0),
.DREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0)
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,38 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48 #(
// Disable all registers
.AREG(0),
.BREG(0),
.B_INPUT("DIRECT"),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.SUBTRACTREG(0),
.LEGACY_MODE("MULT18X18")
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.P(P_48),
.SUBTRACT(1'b0),
.OPMODE(7'b000101),
.CARRYINSEL(2'b00),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,45 @@
module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48E #(
// Disable all registers
.ACASCREG(0),
.A_INPUT("DIRECT"),
.ALUMODEREG(0),
.AREG(0),
.BCASCREG(0),
.B_INPUT("DIRECT"),
.BREG(0),
.MULTCARRYINREG(0),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.USE_MULT("MULT"),
.USE_SIMD("ONE48")
) _TECHMAP_REPLACE_ (
//Data path
.A({{5{A[24]}}, A}),
.B(B),
.C(48'b0),
.P(P_48),
.ALUMODE(4'b0000),
.OPMODE(7'b000101),
.CARRYINSEL(3'b000),
.ACIN(30'b0),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule

View File

@ -1,223 +0,0 @@
module RAMB8BWER (
(* clkbuf_sink *)
input CLKAWRCLK,
(* clkbuf_sink *)
input CLKBRDCLK,
input ENAWREN,
input ENBRDEN,
input REGCEA,
input REGCEBREGCE,
input RSTA,
input RSTBRST,
input [12:0] ADDRAWRADDR,
input [12:0] ADDRBRDADDR,
input [15:0] DIADI,
input [15:0] DIBDI,
input [1:0] DIPADIP,
input [1:0] DIPBDIP,
input [1:0] WEAWEL,
input [1:0] WEBWEU,
/* (* abc9_arrival=<TODO> *) */
output [15:0] DOADO,
/* (* abc9_arrival=<TODO> *) */
output [15:0] DOBDO,
/* (* abc9_arrival=<TODO> *) */
output [1:0] DOPADOP,
/* (* abc9_arrival=<TODO> *) */
output [1:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter RAM_MODE = "TDP";
parameter integer DOA_REG = 0;
parameter integer DOB_REG = 0;
parameter integer DATA_WIDTH_A = 0;
parameter integer DATA_WIDTH_B = 0;
parameter WRITE_MODE_A = "WRITE_FIRST";
parameter WRITE_MODE_B = "WRITE_FIRST";
parameter EN_RSTRAM_A = "TRUE";
parameter EN_RSTRAM_B = "TRUE";
parameter INIT_A = 18'h000000000;
parameter INIT_B = 18'h000000000;
parameter SRVAL_A = 18'h000000000;
parameter SRVAL_B = 18'h000000000;
parameter RST_PRIORITY_A = "CE";
parameter RST_PRIORITY_B = "CE";
parameter RSTTYPE = "SYNC";
parameter SIM_COLLISION_CHECK = "ALL";
endmodule
module RAMB16BWER (
(* clkbuf_sink *)
input CLKA,
(* clkbuf_sink *)
input CLKB,
input ENA,
input ENB,
input REGCEA,
input REGCEB,
input RSTA,
input RSTB,
input [13:0] ADDRA,
input [13:0] ADDRB,
input [31:0] DIA,
input [31:0] DIB,
input [3:0] DIPA,
input [3:0] DIPB,
input [3:0] WEA,
input [3:0] WEB,
/* (* abc9_arrival=<TODO> *) */
output [31:0] DOA,
/* (* abc9_arrival=<TODO> *) */
output [31:0] DOB,
/* (* abc9_arrival=<TODO> *) */
output [3:0] DOPA,
/* (* abc9_arrival=<TODO> *) */
output [3:0] DOPB
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter integer DOA_REG = 0;
parameter integer DOB_REG = 0;
parameter integer DATA_WIDTH_A = 0;
parameter integer DATA_WIDTH_B = 0;
parameter WRITE_MODE_A = "WRITE_FIRST";
parameter WRITE_MODE_B = "WRITE_FIRST";
parameter EN_RSTRAM_A = "TRUE";
parameter EN_RSTRAM_B = "TRUE";
parameter INIT_A = 36'h000000000;
parameter INIT_B = 36'h000000000;
parameter SRVAL_A = 36'h000000000;
parameter SRVAL_B = 36'h000000000;
parameter RST_PRIORITY_A = "CE";
parameter RST_PRIORITY_B = "CE";
parameter RSTTYPE = "SYNC";
parameter SIM_COLLISION_CHECK = "ALL";
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48A1 #(
// Disable all registers
.A0REG(0),
.A1REG(0),
.B0REG(0),
.B1REG(0),
.CARRYINREG(0),
.CARRYINSEL("OPMODE5"),
.CREG(0),
.DREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0)
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
);
assign Y = P_48;
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -1,349 +0,0 @@
// Max delays from https://github.com/SymbiFlow/prjxray-db/blob/f8e0364116b2983ac72a3dc8c509ea1cc79e2e3d/artix7/timings/BRAM_L.sdf#L138-L147
module RAMB18E1 (
(* clkbuf_sink *)
(* invertible_pin = "IS_CLKARDCLK_INVERTED" *)
input CLKARDCLK,
(* clkbuf_sink *)
(* invertible_pin = "IS_CLKBWRCLK_INVERTED" *)
input CLKBWRCLK,
(* invertible_pin = "IS_ENARDEN_INVERTED" *)
input ENARDEN,
(* invertible_pin = "IS_ENBWREN_INVERTED" *)
input ENBWREN,
input REGCEAREGCE,
input REGCEB,
(* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *)
input RSTRAMARSTRAM,
(* invertible_pin = "IS_RSTRAMB_INVERTED" *)
input RSTRAMB,
(* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *)
input RSTREGARSTREG,
(* invertible_pin = "IS_RSTREGB_INVERTED" *)
input RSTREGB,
input [13:0] ADDRARDADDR,
input [13:0] ADDRBWRADDR,
input [15:0] DIADI,
input [15:0] DIBDI,
input [1:0] DIPADIP,
input [1:0] DIPBDIP,
input [1:0] WEA,
input [3:0] WEBWE,
(* abc9_arrival=2454 *)
output [15:0] DOADO,
(* abc9_arrival=2454 *)
output [15:0] DOBDO,
(* abc9_arrival=2454 *)
output [1:0] DOPADOP,
(* abc9_arrival=2454 *)
output [1:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter IS_CLKARDCLK_INVERTED = 1'b0;
parameter IS_CLKBWRCLK_INVERTED = 1'b0;
parameter IS_ENARDEN_INVERTED = 1'b0;
parameter IS_ENBWREN_INVERTED = 1'b0;
parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0;
parameter IS_RSTRAMB_INVERTED = 1'b0;
parameter IS_RSTREGARSTREG_INVERTED = 1'b0;
parameter IS_RSTREGB_INVERTED = 1'b0;
parameter RAM_MODE = "TDP";
parameter integer DOA_REG = 0;
parameter integer DOB_REG = 0;
parameter integer READ_WIDTH_A = 0;
parameter integer READ_WIDTH_B = 0;
parameter integer WRITE_WIDTH_A = 0;
parameter integer WRITE_WIDTH_B = 0;
parameter WRITE_MODE_A = "WRITE_FIRST";
parameter WRITE_MODE_B = "WRITE_FIRST";
parameter SIM_DEVICE = "VIRTEX6";
endmodule
module RAMB36E1 (
(* clkbuf_sink *)
(* invertible_pin = "IS_CLKARDCLK_INVERTED" *)
input CLKARDCLK,
(* clkbuf_sink *)
(* invertible_pin = "IS_CLKBWRCLK_INVERTED" *)
input CLKBWRCLK,
(* invertible_pin = "IS_ENARDEN_INVERTED" *)
input ENARDEN,
(* invertible_pin = "IS_ENBWREN_INVERTED" *)
input ENBWREN,
input REGCEAREGCE,
input REGCEB,
(* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *)
input RSTRAMARSTRAM,
(* invertible_pin = "IS_RSTRAMB_INVERTED" *)
input RSTRAMB,
(* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *)
input RSTREGARSTREG,
(* invertible_pin = "IS_RSTREGB_INVERTED" *)
input RSTREGB,
input [15:0] ADDRARDADDR,
input [15:0] ADDRBWRADDR,
input [31:0] DIADI,
input [31:0] DIBDI,
input [3:0] DIPADIP,
input [3:0] DIPBDIP,
input [3:0] WEA,
input [7:0] WEBWE,
(* abc9_arrival=2454 *)
output [31:0] DOADO,
(* abc9_arrival=2454 *)
output [31:0] DOBDO,
(* abc9_arrival=2454 *)
output [3:0] DOPADOP,
(* abc9_arrival=2454 *)
output [3:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INITP_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter IS_CLKARDCLK_INVERTED = 1'b0;
parameter IS_CLKBWRCLK_INVERTED = 1'b0;
parameter IS_ENARDEN_INVERTED = 1'b0;
parameter IS_ENBWREN_INVERTED = 1'b0;
parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0;
parameter IS_RSTRAMB_INVERTED = 1'b0;
parameter IS_RSTREGARSTREG_INVERTED = 1'b0;
parameter IS_RSTREGB_INVERTED = 1'b0;
parameter RAM_MODE = "TDP";
parameter integer DOA_REG = 0;
parameter integer DOB_REG = 0;
parameter integer READ_WIDTH_A = 0;
parameter integer READ_WIDTH_B = 0;
parameter integer WRITE_WIDTH_A = 0;
parameter integer WRITE_WIDTH_B = 0;
parameter WRITE_MODE_A = "WRITE_FIRST";
parameter WRITE_MODE_B = "WRITE_FIRST";
parameter SIM_DEVICE = "VIRTEX6";
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,384 @@
module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [36863:0] INIT = 36864'bx;
input CLK2;
input CLK3;
input [8:0] A1ADDR;
output [71:0] A1DATA;
input A1EN;
input [8:0] B1ADDR;
input [71:0] B1DATA;
input [7:0] B1EN;
wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0};
wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0};
wire [7:0] DIP, DOP;
wire [63:0] DI, DO;
assign A1DATA = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32],
DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
assign { DIP[7], DI[63:56], DIP[6], DI[55:48], DIP[5], DI[47:40], DIP[4], DI[39:32],
DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
RAMB36E2 #(
.READ_WIDTH_A(72),
.WRITE_WIDTH_B(72),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_36.vh"
) _TECHMAP_REPLACE_ (
.DOUTBDOUT(DO[63:32]),
.DOUTADOUT(DO[31:0]),
.DOUTPBDOUTP(DOP[7:4]),
.DOUTPADOUTP(DOP[3:0]),
.DINBDIN(DI[63:32]),
.DINADIN(DI[31:0]),
.DINPBDINP(DIP[7:4]),
.DINPADINP(DIP[3:0]),
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(4'b0),
.ADDRBWRADDR(B1ADDR_16),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|1),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN),
.SLEEP(|0)
);
endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [18431:0] INIT = 18432'bx;
input CLK2;
input CLK3;
input [8:0] A1ADDR;
output [35:0] A1DATA;
input A1EN;
input [8:0] B1ADDR;
input [35:0] B1DATA;
input [3:0] B1EN;
wire [13:0] A1ADDR_14 = {A1ADDR, 5'b0};
wire [13:0] B1ADDR_14 = {B1ADDR, 5'b0};
wire [3:0] DIP, DOP;
wire [31:0] DI, DO;
assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
RAMB18E2 #(
.READ_WIDTH_A(36),
.WRITE_WIDTH_B(36),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_18.vh"
) _TECHMAP_REPLACE_ (
.DOUTBDOUT(DO[31:16]),
.DOUTADOUT(DO[15:0]),
.DOUTPBDOUTP(DOP[3:2]),
.DOUTPADOUTP(DOP[1:0]),
.DINBDIN(DI[31:16]),
.DINADIN(DI[15:0]),
.DINPBDINP(DIP[3:2]),
.DINPADINP(DIP[1:0]),
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(2'b0),
.ADDRBWRADDR(B1ADDR_14),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|1),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN),
.SLEEP(|0)
);
endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 36;
parameter CFG_ENABLE_B = 4;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [36863:0] INIT = 36864'bx;
input CLK2;
input CLK3;
input [CFG_ABITS-1:0] A1ADDR;
output [CFG_DBITS-1:0] A1DATA;
input A1EN;
input [CFG_ABITS-1:0] B1ADDR;
input [CFG_DBITS-1:0] B1DATA;
input [CFG_ENABLE_B-1:0] B1EN;
wire [15:0] A1ADDR_16 = A1ADDR << (15 - CFG_ABITS);
wire [15:0] B1ADDR_16 = B1ADDR << (15 - CFG_ABITS);
wire [7:0] B1EN_8 = B1EN;
wire [3:0] DIP, DOP;
wire [31:0] DI, DO;
wire [31:0] DOBDO;
wire [3:0] DOPBDOP;
assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
generate if (CFG_DBITS > 8) begin
RAMB36E2 #(
.READ_WIDTH_A(CFG_DBITS),
.READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_36.vh"
) _TECHMAP_REPLACE_ (
.DINADIN(32'hFFFFFFFF),
.DINPADINP(4'hF),
.DOUTADOUT(DO[31:0]),
.DOUTPADOUTP(DOP[3:0]),
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(4'b0),
.DINBDIN(DI),
.DINPBDINP(DIP),
.DOUTBDOUT(DOBDO),
.DOUTPBDOUTP(DOPBDOP),
.ADDRBWRADDR(B1ADDR_16),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|0),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN_8),
.SLEEP(|0)
);
end else begin
RAMB36E2 #(
.READ_WIDTH_A(CFG_DBITS),
.READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_32.vh"
) _TECHMAP_REPLACE_ (
.DINADIN(32'hFFFFFFFF),
.DINPADINP(4'hF),
.DOUTADOUT(DO[31:0]),
.DOUTPADOUTP(DOP[3:0]),
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(4'b0),
.DINBDIN(DI),
.DINPBDINP(DIP),
.DOUTBDOUT(DOBDO),
.DOUTPBDOUTP(DOPBDOP),
.ADDRBWRADDR(B1ADDR_16),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|0),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN_8),
.SLEEP(|0)
);
end endgenerate
endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 18;
parameter CFG_ENABLE_B = 2;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [18431:0] INIT = 18432'bx;
input CLK2;
input CLK3;
input [CFG_ABITS-1:0] A1ADDR;
output [CFG_DBITS-1:0] A1DATA;
input A1EN;
input [CFG_ABITS-1:0] B1ADDR;
input [CFG_DBITS-1:0] B1DATA;
input [CFG_ENABLE_B-1:0] B1EN;
wire [13:0] A1ADDR_14 = A1ADDR << (14 - CFG_ABITS);
wire [13:0] B1ADDR_14 = B1ADDR << (14 - CFG_ABITS);
wire [3:0] B1EN_4 = B1EN;
wire [1:0] DIP, DOP;
wire [15:0] DI, DO;
wire [15:0] DOBDO;
wire [1:0] DOPBDOP;
assign A1DATA = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
generate if (CFG_DBITS > 8) begin
RAMB18E2 #(
.READ_WIDTH_A(CFG_DBITS),
.READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_18.vh"
) _TECHMAP_REPLACE_ (
.DINADIN(16'hFFFF),
.DINPADINP(2'b11),
.DOUTADOUT(DO),
.DOUTPADOUTP(DOP),
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(2'b0),
.DINBDIN(DI),
.DINPBDINP(DIP),
.DOUTBDOUT(DOBDO),
.DOUTPBDOUTP(DOPBDOP),
.ADDRBWRADDR(B1ADDR_14),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|0),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN_4),
.SLEEP(|0)
);
end else begin
RAMB18E2 #(
//.RAM_MODE("TDP"),
.READ_WIDTH_A(CFG_DBITS),
.READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"),
.WRITE_MODE_B("READ_FIRST"),
.DOA_REG(0),
.DOB_REG(0),
.IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_16.vh"
) _TECHMAP_REPLACE_ (
.DINADIN(16'hFFFF),
.DINPADINP(2'b11),
.DOUTADOUT(DO),
.DOUTPADOUTP(DOP),
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(A1EN),
.ADDRENA(|1),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
.WEA(2'b0),
.DINBDIN(DI),
.DINPBDINP(DIP),
.DOUTBDOUT(DOBDO),
.DOUTPBDOUTP(DOPBDOP),
.ADDRBWRADDR(B1ADDR_14),
.CLKBWRCLK(CLK3),
.ENBWREN(|1),
.ADDRENB(|1),
.REGCEB(|0),
.RSTRAMB(|0),
.RSTREGB(|0),
.WEBWE(B1EN_4),
.SLEEP(|0)
);
end endgenerate
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
module \$__MUL27X18 (input [26:0] A, input [17:0] B, output [44:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48E2 #(
// Disable all registers
.ACASCREG(0),
.ADREG(0),
.A_INPUT("DIRECT"),
.ALUMODEREG(0),
.AREG(0),
.BCASCREG(0),
.B_INPUT("DIRECT"),
.BREG(0),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.DREG(0),
.INMODEREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.USE_MULT("MULTIPLY"),
.USE_SIMD("ONE48"),
.AMULTSEL("A"),
.BMULTSEL("B")
) _TECHMAP_REPLACE_ (
//Data path
.A({{3{A[26]}}, A}),
.B(B),
.C(48'b0),
.D(27'b0),
.P(P_48),
.INMODE(5'b00000),
.ALUMODE(4'b0000),
.OPMODE(9'b00000101),
.CARRYINSEL(3'b000),
.ACIN(30'b0),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,19 @@
bram $__XILINX_URAM288
init 0
abits 12
dbits 72
groups 2
ports 1 1
wrmode 0 1
enable 1 9
transp 0 0
clocks 2 2
clkpol 2 2
endbram
match $__XILINX_URAM288
min bits 131072
min efficiency 15
shuffle_enable B
make_transp
endmatch

View File

@ -0,0 +1,47 @@
module \$__XILINX_URAM288 (CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CLKPOL2 = 1;
input CLK2;
input [11:0] A1ADDR;
output [71:0] A1DATA;
input A1EN;
input [11:0] B1ADDR;
input [71:0] B1DATA;
input [8:0] B1EN;
URAM288 #(
.BWE_MODE_A("PARITY_INDEPENDENT"),
.BWE_MODE_B("PARITY_INDEPENDENT"),
.EN_AUTO_SLEEP_MODE("FALSE"),
.IREG_PRE_A("FALSE"),
.IREG_PRE_B("FALSE"),
.IS_CLK_INVERTED(!CLKPOL2),
.OREG_A("FALSE"),
.OREG_B("FALSE")
) _TECHMAP_REPLACE_ (
.ADDR_A({11'b0, A1ADDR}),
.BWE_A(9'b0),
.DIN_A(72'b0),
.EN_A(A1EN),
.RDB_WR_A(1'b0),
.INJECT_DBITERR_A(1'b0),
.INJECT_SBITERR_A(1'b0),
.RST_A(1'b0),
.DOUT_A(A1DATA),
.ADDR_B({11'b0, B1ADDR}),
.BWE_B(B1EN),
.DIN_B(B1DATA),
.EN_B(|B1EN),
.RDB_WR_B(1'b1),
.INJECT_DBITERR_B(1'b0),
.INJECT_SBITERR_B(1'b0),
.RST_B(1'b0),
.CLK(CLK2),
.SLEEP(1'b0)
);
endmodule

View File

@ -0,0 +1,10 @@
read_verilog ../common/add_sub.v
hierarchy -top top
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 10 t:AL_MAP_ADDER
select -assert-count 4 t:AL_MAP_LUT1
select -assert-none t:AL_MAP_LUT1 t:AL_MAP_ADDER %% t:* %D

View File

@ -0,0 +1,11 @@
read_verilog ../common/counter.v
hierarchy -top top
proc
flatten
equiv_opt -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 9 t:AL_MAP_ADDER
select -assert-count 8 t:AL_MAP_SEQ
select -assert-none t:AL_MAP_SEQ t:AL_MAP_ADDER %% t:* %D

View File

@ -0,0 +1,20 @@
read_verilog ../common/dffs.v
design -save read
hierarchy -top dff
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dff # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_SEQ
select -assert-none t:AL_MAP_SEQ %% t:* %D
design -load read
hierarchy -top dffe
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffe # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT3
select -assert-count 1 t:AL_MAP_SEQ
select -assert-none t:AL_MAP_LUT3 t:AL_MAP_SEQ %% t:* %D

18
tests/arch/anlogic/fsm.ys Normal file
View File

@ -0,0 +1,18 @@
read_verilog ../common/fsm.v
hierarchy -top fsm
proc
flatten
equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
miter -equiv -make_assert -flatten gold gate miter
sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd fsm # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT2
select -assert-count 5 t:AL_MAP_LUT5
select -assert-count 1 t:AL_MAP_LUT6
select -assert-count 6 t:AL_MAP_SEQ
select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT5 t:AL_MAP_LUT6 t:AL_MAP_SEQ %% t:* %D

View File

@ -0,0 +1,33 @@
read_verilog ../common/latches.v
design -save read
hierarchy -top latchp
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_anlogic
cd latchp # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT3
select -assert-none t:AL_MAP_LUT3 %% t:* %D
design -load read
hierarchy -top latchn
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_anlogic
cd latchn # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT3
select -assert-none t:AL_MAP_LUT3 %% t:* %D
design -load read
hierarchy -top latchsr
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_anlogic
cd latchsr # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT5
select -assert-none t:AL_MAP_LUT5 %% t:* %D

View File

@ -0,0 +1,11 @@
read_verilog ../common/logic.v
hierarchy -top top
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT1
select -assert-count 6 t:AL_MAP_LUT2
select -assert-count 2 t:AL_MAP_LUT4
select -assert-none t:AL_MAP_LUT1 t:AL_MAP_LUT2 t:AL_MAP_LUT4 %% t:* %D

View File

@ -0,0 +1,21 @@
read_verilog ../common/memory.v
hierarchy -top top
proc
memory -nomap
equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
#ERROR: Failed to import cell gate.mem.0.0.0 (type EG_LOGIC_DRAM16X4) to SAT database.
#sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd top
select -assert-count 8 t:AL_MAP_LUT2
select -assert-count 8 t:AL_MAP_LUT4
select -assert-count 8 t:AL_MAP_LUT5
select -assert-count 36 t:AL_MAP_SEQ
select -assert-count 8 t:EG_LOGIC_DRAM16X4 #Why not AL_LOGIC_BRAM?
select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT4 t:AL_MAP_LUT5 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D

42
tests/arch/anlogic/mux.ys Normal file
View File

@ -0,0 +1,42 @@
read_verilog ../common/mux.v
design -save read
hierarchy -top mux2
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux2 # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT3
select -assert-none t:AL_MAP_LUT3 %% t:* %D
design -load read
hierarchy -top mux4
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
select -assert-count 1 t:AL_MAP_LUT6
select -assert-none t:AL_MAP_LUT6 %% t:* %D
design -load read
hierarchy -top mux8
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
select -assert-count 3 t:AL_MAP_LUT4
select -assert-count 1 t:AL_MAP_LUT6
select -assert-none t:AL_MAP_LUT4 t:AL_MAP_LUT6 %% t:* %D
design -load read
hierarchy -top mux16
proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-count 5 t:AL_MAP_LUT6
select -assert-none t:AL_MAP_LUT6 %% t:* %D

View File

@ -6,7 +6,7 @@ for x in *.ys; do
echo "all:: run-$x"
echo "run-$x:"
echo " @echo 'Running $x..'"
echo " @../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
echo " @../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
done
for s in *.sh; do
if [ "$s" != "run-test.sh" ]; then

View File

@ -0,0 +1,10 @@
read_verilog ../common/shifter.v
hierarchy -top top
proc
flatten
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:AL_MAP_SEQ
select -assert-none t:AL_MAP_SEQ %% t:* %D

View File

@ -0,0 +1,9 @@
read_verilog ../common/tribuf.v
hierarchy -top tristate
proc
flatten
equiv_opt -assert -map +/anlogic/cells_sim.v -map +/simcells.v synth_anlogic # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
select -assert-count 1 t:$_TBUF_
select -assert-none t:$_TBUF_ %% t:* %D

View File

@ -0,0 +1,12 @@
module top
(
input [3:0] x,
input [3:0] y,
output [3:0] A,
output [3:0] B
);
assign A = x + y;
assign B = x - y;
endmodule

43
tests/arch/common/adffs.v Normal file
View File

@ -0,0 +1,43 @@
module adff( input d, clk, clr, output reg q );
initial begin
q = 0;
end
always @( posedge clk, posedge clr )
if ( clr )
q <= 1'b0;
else
q <= d;
endmodule
module adffn( input d, clk, clr, output reg q );
initial begin
q = 0;
end
always @( posedge clk, negedge clr )
if ( !clr )
q <= 1'b0;
else
q <= d;
endmodule
module dffs( input d, clk, pre, clr, output reg q );
initial begin
q = 0;
end
always @( posedge clk )
if ( pre )
q <= 1'b1;
else
q <= d;
endmodule
module ndffnr( input d, clk, pre, clr, output reg q );
initial begin
q = 0;
end
always @( negedge clk )
if ( !clr )
q <= 1'b0;
else
q <= d;
endmodule

View File

@ -0,0 +1,11 @@
module top ( out, clk, reset );
output [7:0] out;
input clk, reset;
reg [7:0] out;
always @(posedge clk, posedge reset)
if (reset)
out <= 8'b0;
else
out <= out + 1;
endmodule

13
tests/arch/common/dffs.v Normal file
View File

@ -0,0 +1,13 @@
module dff ( input d, clk, output reg q );
always @( posedge clk )
q <= d;
endmodule
module dffe( input d, clk, en, output reg q );
initial begin
q = 0;
end
always @( posedge clk )
if ( en )
q <= d;
endmodule

51
tests/arch/common/fsm.v Normal file
View File

@ -0,0 +1,51 @@
module fsm ( clock, reset, req_0, req_1, gnt_0, gnt_1 );
input clock,reset,req_0,req_1;
output gnt_0,gnt_1;
wire clock,reset,req_0,req_1;
reg gnt_0,gnt_1;
parameter SIZE = 3;
parameter IDLE = 3'b001;
parameter GNT0 = 3'b010;
parameter GNT1 = 3'b100;
parameter GNT2 = 3'b101;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
always @ (posedge clock)
begin : FSM
if (reset == 1'b1) begin
state <= #1 IDLE;
gnt_0 <= 0;
gnt_1 <= 0;
end
else
case(state)
IDLE : if (req_0 == 1'b1) begin
state <= #1 GNT0;
gnt_0 <= 1;
end else if (req_1 == 1'b1) begin
gnt_1 <= 1;
state <= #1 GNT0;
end else begin
state <= #1 IDLE;
end
GNT0 : if (req_0 == 1'b1) begin
state <= #1 GNT0;
end else begin
gnt_0 <= 0;
state <= #1 IDLE;
end
GNT1 : if (req_1 == 1'b1) begin
state <= #1 GNT2;
gnt_1 <= req_0;
end
GNT2 : if (req_0 == 1'b1) begin
state <= #1 GNT1;
gnt_1 <= req_1;
end
default : state <= #1 IDLE;
endcase
end
endmodule

View File

@ -0,0 +1,21 @@
module latchp ( input d, clk, en, output reg q );
always @*
if ( en )
q <= d;
endmodule
module latchn ( input d, clk, en, output reg q );
always @*
if ( !en )
q <= d;
endmodule
module latchsr ( input d, clk, en, clr, pre, output reg q );
always @*
if ( clr )
q <= 1'b0;
else if ( pre )
q <= 1'b1;
else if ( en )
q <= d;
endmodule

16
tests/arch/common/logic.v Normal file
View File

@ -0,0 +1,16 @@
module top
(
input [0:7] in,
output B1,B2,B3,B4,B5,B6,B7,B8,B9,B10
);
assign B1 = in[0] & in[1];
assign B2 = in[0] | in[1];
assign B3 = in[0] ~& in[1];
assign B4 = in[0] ~| in[1];
assign B5 = in[0] ^ in[1];
assign B6 = in[0] ~^ in[1];
assign B7 = ~in[0];
assign B8 = in[0];
assign B9 = in[0:1] && in [2:3];
assign B10 = in[0:1] || in [2:3];
endmodule

9
tests/arch/common/mul.v Normal file
View File

@ -0,0 +1,9 @@
module top
(
input [5:0] x,
input [5:0] y,
output [11:0] A,
);
assign A = x * y;
endmodule

60
tests/arch/common/mux.v Normal file
View File

@ -0,0 +1,60 @@
module mux2 (S,A,B,Y);
input S;
input A,B;
output reg Y;
always @(*)
Y = (S)? B : A;
endmodule
module mux4 ( S, D, Y );
input[1:0] S;
input[3:0] D;
output Y;
reg Y;
wire[1:0] S;
wire[3:0] D;
always @*
begin
case( S )
0 : Y = D[0];
1 : Y = D[1];
2 : Y = D[2];
3 : Y = D[3];
endcase
end
endmodule
module mux8 ( S, D, Y );
input[2:0] S;
input[7:0] D;
output Y;
reg Y;
wire[2:0] S;
wire[7:0] D;
always @*
begin
case( S )
0 : Y = D[0];
1 : Y = D[1];
2 : Y = D[2];
3 : Y = D[3];
4 : Y = D[4];
5 : Y = D[5];
6 : Y = D[6];
7 : Y = D[7];
endcase
end
endmodule
module mux16 (D, S, Y);
input [15:0] D;
input [3:0] S;
output Y;
assign Y = D[S];
endmodule

Some files were not shown because too many files have changed in this diff Show More