mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into eddie/deferred_top
This commit is contained in:
		
						commit
						d6a84a78a7
					
				
					 72 changed files with 1855 additions and 413 deletions
				
			
		| 
						 | 
					@ -36,6 +36,8 @@ Yosys 0.9 .. Yosys 0.9-dev
 | 
				
			||||||
    - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
 | 
					    - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
 | 
				
			||||||
    - Removed "ice40_unlut"
 | 
					    - Removed "ice40_unlut"
 | 
				
			||||||
    - Improvements in pmgen: slices, choices, define, generate
 | 
					    - Improvements in pmgen: slices, choices, define, generate
 | 
				
			||||||
 | 
					    - Added "xilinx_srl" for Xilinx shift register extraction
 | 
				
			||||||
 | 
					    - Removed "shregmap -tech xilinx" (superseded by "xilinx_srl")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Yosys 0.8 .. Yosys 0.9
 | 
					Yosys 0.8 .. Yosys 0.9
 | 
				
			||||||
----------------------
 | 
					----------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -115,7 +115,7 @@ LDFLAGS += -rdynamic
 | 
				
			||||||
LDLIBS += -lrt
 | 
					LDLIBS += -lrt
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_VER := 0.9+1
 | 
					YOSYS_VER := 0.9+36
 | 
				
			||||||
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
 | 
					GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
 | 
				
			||||||
OBJS = kernel/version_$(GIT_REV).o
 | 
					OBJS = kernel/version_$(GIT_REV).o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -709,6 +709,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
 | 
				
			||||||
	+cd tests/opt && bash run-test.sh
 | 
						+cd tests/opt && bash run-test.sh
 | 
				
			||||||
	+cd tests/aiger && bash run-test.sh $(ABCOPT)
 | 
						+cd tests/aiger && bash run-test.sh $(ABCOPT)
 | 
				
			||||||
	+cd tests/arch && bash run-test.sh
 | 
						+cd tests/arch && bash run-test.sh
 | 
				
			||||||
 | 
						+cd tests/ice40 && bash run-test.sh $(SEEDOPT)
 | 
				
			||||||
	@echo ""
 | 
						@echo ""
 | 
				
			||||||
	@echo "  Passed \"make test\"."
 | 
						@echo "  Passed \"make test\"."
 | 
				
			||||||
	@echo ""
 | 
						@echo ""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
					@ -330,7 +330,7 @@ Verilog Attributes and non-standard features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The ``parameter`` and ``localparam`` attributes are used to mark wires
 | 
					- The ``parameter`` and ``localparam`` attributes are used to mark wires
 | 
				
			||||||
  that represent module parameters or localparams (when the HDL front-end
 | 
					  that represent module parameters or localparams (when the HDL front-end
 | 
				
			||||||
  is run in -pwires mode).
 | 
					  is run in ``-pwires`` mode).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
 | 
					- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
 | 
				
			||||||
  module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
 | 
					  module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
 | 
				
			||||||
| 
						 | 
					@ -347,6 +347,23 @@ Verilog Attributes and non-standard features
 | 
				
			||||||
  it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
 | 
					  it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
 | 
				
			||||||
  from inserting another pad cell on it.
 | 
					  from inserting another pad cell on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The module attribute ``abc_box_id`` specifies a positive integer linking a
 | 
				
			||||||
 | 
					  blackbox or whitebox definition to a corresponding entry in a `abc9`
 | 
				
			||||||
 | 
					  box-file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The port attribute ``abc_scc_break`` indicates a module input port that will
 | 
				
			||||||
 | 
					  be treated as a primary output during `abc9` techmapping. Doing so eliminates
 | 
				
			||||||
 | 
					  the possibility of a strongly-connected component (i.e. a combinatorial loop)
 | 
				
			||||||
 | 
					  existing. Typically, this is specified for sequential inputs on otherwise
 | 
				
			||||||
 | 
					  combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D`
 | 
				
			||||||
 | 
					  port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths
 | 
				
			||||||
 | 
					  as a combinatorial loop.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The port attribute ``abc_carry`` marks the carry-in (if an input port) and
 | 
				
			||||||
 | 
					  carry-out (if output port) ports of a box. This information is necessary for
 | 
				
			||||||
 | 
					  `abc9` to preserve the integrity of carry-chains. Specifying this attribute
 | 
				
			||||||
 | 
					  onto a bus port will affect only its most significant bit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
 | 
					- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
 | 
				
			||||||
  the non-standard ``{* ... *}`` attribute syntax to set default attributes
 | 
					  the non-standard ``{* ... *}`` attribute syntax to set default attributes
 | 
				
			||||||
  for everything that comes after the ``{* ... *}`` statement. (Reset
 | 
					  for everything that comes after the ``{* ... *}`` statement. (Reset
 | 
				
			||||||
| 
						 | 
					@ -423,23 +440,6 @@ Verilog Attributes and non-standard features
 | 
				
			||||||
  blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
 | 
					  blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
 | 
				
			||||||
  functionality. (By default specify .. endspecify blocks are ignored.)
 | 
					  functionality. (By default specify .. endspecify blocks are ignored.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The module attribute ``abc_box_id`` specifies a positive integer linking a
 | 
					 | 
				
			||||||
  blackbox or whitebox definition to a corresponding entry in a `abc9`
 | 
					 | 
				
			||||||
  box-file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- The port attribute ``abc_scc_break`` indicates a module input port that will
 | 
					 | 
				
			||||||
  be treated as a primary output during `abc9` techmapping. Doing so eliminates
 | 
					 | 
				
			||||||
  the possibility of a strongly-connected component (i.e. a combinatorial loop)
 | 
					 | 
				
			||||||
  existing. Typically, this is specified for sequential inputs on otherwise
 | 
					 | 
				
			||||||
  combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D`
 | 
					 | 
				
			||||||
  port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths
 | 
					 | 
				
			||||||
  as a combinatorial loop.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- The port attribute ``abc_carry`` marks the carry-in (if an input port) and
 | 
					 | 
				
			||||||
  carry-out (if output port) ports of a box. This information is necessary for
 | 
					 | 
				
			||||||
  `abc9` to preserve the integrity of carry-chains. Specifying this attribute
 | 
					 | 
				
			||||||
  onto a bus port will affect only its most significant bit.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Non-standard or SystemVerilog features for formal verification
 | 
					Non-standard or SystemVerilog features for formal verification
 | 
				
			||||||
==============================================================
 | 
					==============================================================
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,11 +261,12 @@ struct XAigerWriter
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else {
 | 
								else {
 | 
				
			||||||
				bool cell_known = cell->known();
 | 
									bool cell_known = inst_module || cell->known();
 | 
				
			||||||
				for (const auto &c : cell->connections()) {
 | 
									for (const auto &c : cell->connections()) {
 | 
				
			||||||
					if (c.second.is_fully_const()) continue;
 | 
										if (c.second.is_fully_const()) continue;
 | 
				
			||||||
					auto is_input = !cell_known || cell->input(c.first);
 | 
										auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr;
 | 
				
			||||||
					auto is_output = !cell_known || cell->output(c.first);
 | 
										auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first);
 | 
				
			||||||
 | 
										auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first);
 | 
				
			||||||
					if (!is_input && !is_output)
 | 
										if (!is_input && !is_output)
 | 
				
			||||||
						log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type));
 | 
											log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -974,7 +974,7 @@ void AigerReader::post_process()
 | 
				
			||||||
	// operate (and run checks on) this one module
 | 
						// operate (and run checks on) this one module
 | 
				
			||||||
	RTLIL::Design *mapped_design = new RTLIL::Design;
 | 
						RTLIL::Design *mapped_design = new RTLIL::Design;
 | 
				
			||||||
	mapped_design->add(module);
 | 
						mapped_design->add(module);
 | 
				
			||||||
	Pass::call(mapped_design, "clean");
 | 
						Pass::call(mapped_design, "clean -purge");
 | 
				
			||||||
	mapped_design->modules_.erase(module->name);
 | 
						mapped_design->modules_.erase(module->name);
 | 
				
			||||||
	delete mapped_design;
 | 
						delete mapped_design;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,7 +664,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
		if (arg == "%D") {
 | 
							if (arg == "%D") {
 | 
				
			||||||
			if (work_stack.size() < 2)
 | 
								if (work_stack.size() < 2)
 | 
				
			||||||
				log_cmd_error("Must have at least two elements on the stack for operator %%d.\n");
 | 
									log_cmd_error("Must have at least two elements on the stack for operator %%D.\n");
 | 
				
			||||||
			select_op_diff(design, work_stack[work_stack.size()-1], work_stack[work_stack.size()-2]);
 | 
								select_op_diff(design, work_stack[work_stack.size()-1], work_stack[work_stack.size()-2]);
 | 
				
			||||||
			work_stack[work_stack.size()-2] = work_stack[work_stack.size()-1];
 | 
								work_stack[work_stack.size()-2] = work_stack[work_stack.size()-1];
 | 
				
			||||||
			work_stack.pop_back();
 | 
								work_stack.pop_back();
 | 
				
			||||||
| 
						 | 
					@ -693,7 +693,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
		if (arg == "%C") {
 | 
							if (arg == "%C") {
 | 
				
			||||||
			if (work_stack.size() < 1)
 | 
								if (work_stack.size() < 1)
 | 
				
			||||||
				log_cmd_error("Must have at least one element on the stack for operator %%M.\n");
 | 
									log_cmd_error("Must have at least one element on the stack for operator %%C.\n");
 | 
				
			||||||
			select_op_module_to_cells(design, work_stack[work_stack.size()-1]);
 | 
								select_op_module_to_cells(design, work_stack[work_stack.size()-1]);
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
		if (arg == "%c") {
 | 
							if (arg == "%c") {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
# --------------------------------------
 | 
					# --------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OBJS += passes/pmgen/test_pmgen.o
 | 
					OBJS += passes/pmgen/test_pmgen.o
 | 
				
			||||||
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h
 | 
					passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h passes/pmgen/xilinx_srl_pm.h
 | 
				
			||||||
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
 | 
					$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------
 | 
					# --------------------------------------
 | 
				
			||||||
| 
						 | 
					@ -30,3 +30,9 @@ PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
 | 
					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 && python3 $< -o $@ -p peepopt $(filter-out $<,$^)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJS += passes/pmgen/xilinx_srl.o
 | 
				
			||||||
 | 
					passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h
 | 
				
			||||||
 | 
					$(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,11 +64,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool();
 | 
						bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mul_signed) {
 | 
					 | 
				
			||||||
		log("  inference of signed iCE40 DSP arithmetic is currently not supported.\n");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log("  replacing $mul with SB_MAC16 cell.\n");
 | 
						log("  replacing $mul with SB_MAC16 cell.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
 | 
						Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ bool did_something;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "passes/pmgen/test_pmgen_pm.h"
 | 
					#include "passes/pmgen/test_pmgen_pm.h"
 | 
				
			||||||
#include "passes/pmgen/ice40_dsp_pm.h"
 | 
					#include "passes/pmgen/ice40_dsp_pm.h"
 | 
				
			||||||
 | 
					#include "passes/pmgen/xilinx_srl_pm.h"
 | 
				
			||||||
#include "passes/pmgen/peepopt_pm.h"
 | 
					#include "passes/pmgen/peepopt_pm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void reduce_chain(test_pmgen_pm &pm)
 | 
					void reduce_chain(test_pmgen_pm &pm)
 | 
				
			||||||
| 
						 | 
					@ -180,7 +181,7 @@ void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const
 | 
				
			||||||
		while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
 | 
							while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (timeout++ > 10000)
 | 
								if (timeout++ > 10000)
 | 
				
			||||||
				log_error("pmgen generator is stuck: 10000 iterations an no matching module generated.\n");
 | 
									log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			pm matcher(mod, mod->cells());
 | 
								pm matcher(mod, mod->cells());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,7 +217,7 @@ void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const
 | 
				
			||||||
			run(matcher, [](){});
 | 
								run(matcher, [](){});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (submodcnt)
 | 
							if (submodcnt && maxsubcnt < (1 << 16))
 | 
				
			||||||
			maxsubcnt *= 2;
 | 
								maxsubcnt *= 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		design->remove(mod);
 | 
							design->remove(mod);
 | 
				
			||||||
| 
						 | 
					@ -349,13 +350,18 @@ struct TestPmgenPass : public Pass {
 | 
				
			||||||
		if (pattern == "ice40_dsp")
 | 
							if (pattern == "ice40_dsp")
 | 
				
			||||||
			return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
 | 
								return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (pattern == "xilinx_srl.fixed")
 | 
				
			||||||
 | 
								return GENERATE_PATTERN(xilinx_srl_pm, fixed);
 | 
				
			||||||
 | 
							if (pattern == "xilinx_srl.variable")
 | 
				
			||||||
 | 
								return GENERATE_PATTERN(xilinx_srl_pm, variable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pattern == "peepopt-muldiv")
 | 
							if (pattern == "peepopt-muldiv")
 | 
				
			||||||
			return GENERATE_PATTERN(peepopt_pm, muldiv);
 | 
								return GENERATE_PATTERN(peepopt_pm, muldiv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pattern == "peepopt-shiftmul")
 | 
							if (pattern == "peepopt-shiftmul")
 | 
				
			||||||
			return GENERATE_PATTERN(peepopt_pm, shiftmul);
 | 
								return GENERATE_PATTERN(peepopt_pm, shiftmul);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log_cmd_error("Unkown pattern: %s\n", pattern.c_str());
 | 
							log_cmd_error("Unknown pattern: %s\n", pattern.c_str());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										258
									
								
								passes/pmgen/xilinx_srl.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								passes/pmgen/xilinx_srl.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,258 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  yosys -- Yosys Open SYnthesis Suite
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
				
			||||||
 | 
					 *            (C) 2019  Eddie Hung    <eddie@fpgeh.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  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"
 | 
				
			||||||
 | 
					#include "kernel/sigtools.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USING_YOSYS_NAMESPACE
 | 
				
			||||||
 | 
					PRIVATE_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "passes/pmgen/xilinx_srl_pm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void run_fixed(xilinx_srl_pm &pm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto &st = pm.st_fixed;
 | 
				
			||||||
 | 
						auto &ud = pm.ud_fixed;
 | 
				
			||||||
 | 
						log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SigSpec initval;
 | 
				
			||||||
 | 
						for (auto cell : ud.longest_chain) {
 | 
				
			||||||
 | 
							log_debug("    %s\n", log_id(cell));
 | 
				
			||||||
 | 
							if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) {
 | 
				
			||||||
 | 
								SigBit Q = cell->getPort(ID(Q));
 | 
				
			||||||
 | 
								log_assert(Q.wire);
 | 
				
			||||||
 | 
								auto it = Q.wire->attributes.find(ID(init));
 | 
				
			||||||
 | 
								if (it != Q.wire->attributes.end()) {
 | 
				
			||||||
 | 
									auto &i = it->second[Q.offset];
 | 
				
			||||||
 | 
									initval.append(i);
 | 
				
			||||||
 | 
									i = State::Sx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									initval.append(State::Sx);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (cell->type.in(ID(FDRE), ID(FDRE_1))) {
 | 
				
			||||||
 | 
								if (cell->parameters.at(ID(INIT), State::S0).as_bool())
 | 
				
			||||||
 | 
									initval.append(State::S1);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									initval.append(State::S0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
							pm.autoremove(cell);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto first_cell = ud.longest_chain.back();
 | 
				
			||||||
 | 
						auto last_cell = ud.longest_chain.front();
 | 
				
			||||||
 | 
						Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_));
 | 
				
			||||||
 | 
						pm.module->swap_names(c, first_cell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) {
 | 
				
			||||||
 | 
							c->setParam(ID(DEPTH), GetSize(ud.longest_chain));
 | 
				
			||||||
 | 
							c->setParam(ID(INIT), initval.as_const());
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								c->setParam(ID(CLKPOL), 1);
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1)))
 | 
				
			||||||
 | 
								c->setParam(ID(CLKPOL), 0);
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID(FDRE))) {
 | 
				
			||||||
 | 
								if (!first_cell->parameters.at(ID(IS_C_INVERTED), State::S0).as_bool())
 | 
				
			||||||
 | 
									c->setParam(ID(CLKPOL), 1);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									c->setParam(ID(CLKPOL), 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								c->setParam(ID(ENPOL), 1);
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_)))
 | 
				
			||||||
 | 
								c->setParam(ID(ENPOL), 0);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								c->setParam(ID(ENPOL), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c->setPort(ID(C), first_cell->getPort(ID(C)));
 | 
				
			||||||
 | 
							c->setPort(ID(D), first_cell->getPort(ID(D)));
 | 
				
			||||||
 | 
							c->setPort(ID(Q), last_cell->getPort(ID(Q)));
 | 
				
			||||||
 | 
							c->setPort(ID(L), GetSize(ud.longest_chain)-1);
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), State::S1);
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), first_cell->getPort(ID(E)));
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID(FDRE), ID(FDRE_1)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), first_cell->getPort(ID(CE)));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							log_abort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log("    -> %s (%s)\n", log_id(c), log_id(c->type));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void run_variable(xilinx_srl_pm &pm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto &st = pm.st_variable;
 | 
				
			||||||
 | 
						auto &ud = pm.ud_variable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SigSpec initval;
 | 
				
			||||||
 | 
						for (const auto &i : ud.chain) {
 | 
				
			||||||
 | 
							auto cell = i.first;
 | 
				
			||||||
 | 
							auto slice = i.second;
 | 
				
			||||||
 | 
							log_debug("    %s\n", log_id(cell));
 | 
				
			||||||
 | 
							if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) {
 | 
				
			||||||
 | 
								SigBit Q = cell->getPort(ID(Q))[slice];
 | 
				
			||||||
 | 
								log_assert(Q.wire);
 | 
				
			||||||
 | 
								auto it = Q.wire->attributes.find(ID(init));
 | 
				
			||||||
 | 
								if (it != Q.wire->attributes.end()) {
 | 
				
			||||||
 | 
									auto &i = it->second[Q.offset];
 | 
				
			||||||
 | 
									initval.append(i);
 | 
				
			||||||
 | 
									i = State::Sx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									initval.append(State::Sx);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pm.autoremove(st.shiftx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto first_cell = ud.chain.back().first;
 | 
				
			||||||
 | 
						auto first_slice = ud.chain.back().second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_));
 | 
				
			||||||
 | 
						pm.module->swap_names(c, first_cell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) {
 | 
				
			||||||
 | 
							c->setParam(ID(DEPTH), GetSize(ud.chain));
 | 
				
			||||||
 | 
							c->setParam(ID(INIT), initval.as_const());
 | 
				
			||||||
 | 
							Const clkpol, enpol;
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								clkpol = 1;
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_)))
 | 
				
			||||||
 | 
								clkpol = 0;
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($dff), ID($dffe)))
 | 
				
			||||||
 | 
								clkpol = first_cell->getParam(ID(CLK_POLARITY));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								enpol = 1;
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_)))
 | 
				
			||||||
 | 
								enpol = 0;
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($dffe)))
 | 
				
			||||||
 | 
								enpol = first_cell->getParam(ID(EN_POLARITY));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								enpol = 2;
 | 
				
			||||||
 | 
							c->setParam(ID(CLKPOL), clkpol);
 | 
				
			||||||
 | 
							c->setParam(ID(ENPOL), enpol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								c->setPort(ID(C), first_cell->getPort(ID(C)));
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($dff), ID($dffe)))
 | 
				
			||||||
 | 
								c->setPort(ID(C), first_cell->getPort(ID(CLK)));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
							c->setPort(ID(D), first_cell->getPort(ID(D))[first_slice]);
 | 
				
			||||||
 | 
							c->setPort(ID(Q), st.shiftx->getPort(ID(Y)));
 | 
				
			||||||
 | 
							c->setPort(ID(L), st.shiftx->getPort(ID(B)));
 | 
				
			||||||
 | 
							if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($dff)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), State::S1);
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), first_cell->getPort(ID(E)));
 | 
				
			||||||
 | 
							else if (first_cell->type.in(ID($dffe)))
 | 
				
			||||||
 | 
								c->setPort(ID(E), first_cell->getPort(ID(EN)));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							log_abort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log("    -> %s (%s)\n", log_id(c), log_id(c->type));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct XilinxSrlPass : public Pass {
 | 
				
			||||||
 | 
						XilinxSrlPass() : Pass("xilinx_srl", "Xilinx shift register extraction") { }
 | 
				
			||||||
 | 
						void help() YS_OVERRIDE
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    xilinx_srl [options] [selection]\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("This pass converts chains of built-in flops (bit-level: $_DFF_[NP]_, $_DFFE_*\n");
 | 
				
			||||||
 | 
							log("and word-level: $dff, $dffe) as well as Xilinx flops (FDRE, FDRE_1) into a\n");
 | 
				
			||||||
 | 
							log("$__XILINX_SHREG cell. Chains must be of the same cell type, clock, clock polarity,\n");
 | 
				
			||||||
 | 
							log("enable, and enable polarity (where relevant).\n");
 | 
				
			||||||
 | 
							log("Flops with resets cannot be mapped to Xilinx devices and will not be inferred.");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -minlen N\n");
 | 
				
			||||||
 | 
							log("        min length of shift register (default = 3)\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -fixed\n");
 | 
				
			||||||
 | 
							log("        infer fixed-length shift registers.\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -variable\n");
 | 
				
			||||||
 | 
							log("        infer variable-length shift registers (i.e. fixed-length shifts where\n");
 | 
				
			||||||
 | 
							log("        each element also fans-out to a $shiftx cell).\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool fixed = false;
 | 
				
			||||||
 | 
							bool variable = false;
 | 
				
			||||||
 | 
							int minlen = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							size_t argidx;
 | 
				
			||||||
 | 
							for (argidx = 1; argidx < args.size(); argidx++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (args[argidx] == "-minlen" && argidx+1 < args.size()) {
 | 
				
			||||||
 | 
									minlen = atoi(args[++argidx].c_str());
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-fixed") {
 | 
				
			||||||
 | 
									fixed = true;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-variable") {
 | 
				
			||||||
 | 
									variable = true;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							extra_args(args, argidx, design);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!fixed && !variable)
 | 
				
			||||||
 | 
								log_cmd_error("'-fixed' and/or '-variable' must be specified.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (auto module : design->selected_modules()) {
 | 
				
			||||||
 | 
								auto pm = xilinx_srl_pm(module, module->selected_cells());
 | 
				
			||||||
 | 
								pm.ud_fixed.minlen = minlen;
 | 
				
			||||||
 | 
								pm.ud_variable.minlen = minlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (fixed)
 | 
				
			||||||
 | 
									pm.run_fixed(run_fixed);
 | 
				
			||||||
 | 
								if (variable)
 | 
				
			||||||
 | 
									pm.run_variable(run_variable);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					} XilinxSrlPass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PRIVATE_NAMESPACE_END
 | 
				
			||||||
							
								
								
									
										326
									
								
								passes/pmgen/xilinx_srl.pmg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								passes/pmgen/xilinx_srl.pmg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,326 @@
 | 
				
			||||||
 | 
					pattern fixed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					state <IdString> clk_port en_port
 | 
				
			||||||
 | 
					udata <vector<Cell*>> chain longest_chain
 | 
				
			||||||
 | 
					udata <pool<Cell*>> non_first_cells
 | 
				
			||||||
 | 
					udata <int> minlen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code
 | 
				
			||||||
 | 
						non_first_cells.clear();
 | 
				
			||||||
 | 
						subpattern(setup);
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match first
 | 
				
			||||||
 | 
						select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
 | 
				
			||||||
 | 
						select !first->has_keep_attr()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero()
 | 
				
			||||||
 | 
						filter !non_first_cells.count(first)
 | 
				
			||||||
 | 
					generate
 | 
				
			||||||
 | 
						SigSpec C = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
						SigSpec D = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
						SigSpec Q = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
						auto r = rng(8);
 | 
				
			||||||
 | 
						Cell* cell;
 | 
				
			||||||
 | 
						switch (r)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							cell = module->addCell(NEW_ID, \FDRE);
 | 
				
			||||||
 | 
							cell->setPort(\C, C);
 | 
				
			||||||
 | 
							cell->setPort(\D, D);
 | 
				
			||||||
 | 
							cell->setPort(\Q, Q);
 | 
				
			||||||
 | 
							cell->setPort(\CE, module->addWire(NEW_ID));
 | 
				
			||||||
 | 
							if (r & 1)
 | 
				
			||||||
 | 
								cell->setPort(\R, module->addWire(NEW_ID));
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								if (rng(2) == 0)
 | 
				
			||||||
 | 
									cell->setPort(\R, State::S0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							cell = module->addDffGate(NEW_ID, C, D, Q, r & 1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
						case 5:
 | 
				
			||||||
 | 
						case 6:
 | 
				
			||||||
 | 
						case 7:
 | 
				
			||||||
 | 
							cell = module->addDffeGate(NEW_ID, C, module->addWire(NEW_ID), D, Q, r & 1, r & 2);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default: log_abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code clk_port en_port
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1))
 | 
				
			||||||
 | 
							clk_port = \C;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_))
 | 
				
			||||||
 | 
							en_port = IdString();
 | 
				
			||||||
 | 
						else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_))
 | 
				
			||||||
 | 
							en_port = \E;
 | 
				
			||||||
 | 
						else if (first->type.in(\FDRE, \FDRE_1))
 | 
				
			||||||
 | 
							en_port = \CE;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						longest_chain.clear();
 | 
				
			||||||
 | 
						chain.push_back(first);
 | 
				
			||||||
 | 
						subpattern(tail);
 | 
				
			||||||
 | 
					finally
 | 
				
			||||||
 | 
						chain.pop_back();
 | 
				
			||||||
 | 
						log_assert(chain.empty());
 | 
				
			||||||
 | 
						if (GetSize(longest_chain) >= minlen)
 | 
				
			||||||
 | 
							accept;
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subpattern setup
 | 
				
			||||||
 | 
					arg clk_port
 | 
				
			||||||
 | 
					arg en_port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match first
 | 
				
			||||||
 | 
						select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
 | 
				
			||||||
 | 
						select !first->has_keep_attr()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero()
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code clk_port en_port
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1))
 | 
				
			||||||
 | 
							clk_port = \C;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_))
 | 
				
			||||||
 | 
							en_port = IdString();
 | 
				
			||||||
 | 
						else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_))
 | 
				
			||||||
 | 
							en_port = \E;
 | 
				
			||||||
 | 
						else if (first->type.in(\FDRE, \FDRE_1))
 | 
				
			||||||
 | 
							en_port = \CE;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match next
 | 
				
			||||||
 | 
						select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
 | 
				
			||||||
 | 
						select !next->has_keep_attr()
 | 
				
			||||||
 | 
						select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep)
 | 
				
			||||||
 | 
						select nusers(port(next, \Q)) == 2
 | 
				
			||||||
 | 
						index <IdString> next->type === first->type
 | 
				
			||||||
 | 
						index <SigBit> port(next, \Q) === port(first, \D)
 | 
				
			||||||
 | 
						filter port(next, clk_port) == port(first, clk_port)
 | 
				
			||||||
 | 
						filter en_port == IdString() || port(next, en_port) == port(first, en_port)
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero()
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code
 | 
				
			||||||
 | 
						non_first_cells.insert(next);
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subpattern tail
 | 
				
			||||||
 | 
					arg first
 | 
				
			||||||
 | 
					arg clk_port
 | 
				
			||||||
 | 
					arg en_port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match next
 | 
				
			||||||
 | 
						semioptional
 | 
				
			||||||
 | 
						select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
 | 
				
			||||||
 | 
						select !next->has_keep_attr()
 | 
				
			||||||
 | 
						select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep)
 | 
				
			||||||
 | 
						select nusers(port(next, \Q)) == 2
 | 
				
			||||||
 | 
						index <IdString> next->type === chain.back()->type
 | 
				
			||||||
 | 
						index <SigBit> port(next, \Q) === port(chain.back(), \D)
 | 
				
			||||||
 | 
						filter port(next, clk_port) == port(first, clk_port)
 | 
				
			||||||
 | 
						filter en_port == IdString() || port(next, en_port) == port(first, en_port)
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool()
 | 
				
			||||||
 | 
						filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero()
 | 
				
			||||||
 | 
					generate
 | 
				
			||||||
 | 
						Cell *cell = module->addCell(NEW_ID, chain.back()->type);
 | 
				
			||||||
 | 
						cell->setPort(\C, chain.back()->getPort(\C));
 | 
				
			||||||
 | 
						cell->setPort(\D, module->addWire(NEW_ID));
 | 
				
			||||||
 | 
						cell->setPort(\Q, chain.back()->getPort(\D));
 | 
				
			||||||
 | 
						if (cell->type == \FDRE) {
 | 
				
			||||||
 | 
							if (rng(2) == 0)
 | 
				
			||||||
 | 
								cell->setPort(\R, chain.back()->connections_.at(\R, State::S0));
 | 
				
			||||||
 | 
							cell->setPort(\CE, chain.back()->getPort(\CE));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (cell->type.begins_with("$_DFFE_"))
 | 
				
			||||||
 | 
							cell->setPort(\E, chain.back()->getPort(\E));
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code
 | 
				
			||||||
 | 
						if (next) {
 | 
				
			||||||
 | 
							chain.push_back(next);
 | 
				
			||||||
 | 
							subpattern(tail);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (GetSize(chain) > GetSize(longest_chain))
 | 
				
			||||||
 | 
								longest_chain = chain;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					finally
 | 
				
			||||||
 | 
						if (next)
 | 
				
			||||||
 | 
							chain.pop_back();
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pattern variable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					state <IdString> clk_port en_port
 | 
				
			||||||
 | 
					state <int> shiftx_width
 | 
				
			||||||
 | 
					state <int> slice
 | 
				
			||||||
 | 
					udata <int> minlen
 | 
				
			||||||
 | 
					udata <vector<pair<Cell*,int>>> chain
 | 
				
			||||||
 | 
					udata <pool<SigBit>> chain_bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code
 | 
				
			||||||
 | 
						chain_bits.clear();
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match shiftx
 | 
				
			||||||
 | 
						select shiftx->type.in($shiftx)
 | 
				
			||||||
 | 
						select !shiftx->has_keep_attr()
 | 
				
			||||||
 | 
						select param(shiftx, \Y_WIDTH).as_int() == 1
 | 
				
			||||||
 | 
						filter param(shiftx, \A_WIDTH).as_int() >= minlen
 | 
				
			||||||
 | 
					generate
 | 
				
			||||||
 | 
						minlen = 3;
 | 
				
			||||||
 | 
						module->addShiftx(NEW_ID, module->addWire(NEW_ID, rng(6)+minlen), module->addWire(NEW_ID, 3), module->addWire(NEW_ID));
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code shiftx_width
 | 
				
			||||||
 | 
						shiftx_width = param(shiftx, \A_WIDTH).as_int();
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match first
 | 
				
			||||||
 | 
						select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe)
 | 
				
			||||||
 | 
						select !first->has_keep_attr()
 | 
				
			||||||
 | 
						select port(first, \Q)[0].wire && !port(first, \Q)[0].wire->get_bool_attribute(\keep)
 | 
				
			||||||
 | 
						slice idx GetSize(port(first, \Q))
 | 
				
			||||||
 | 
						select nusers(port(first, \Q)[idx]) <= 2
 | 
				
			||||||
 | 
						index <SigBit> port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1]
 | 
				
			||||||
 | 
						set slice idx
 | 
				
			||||||
 | 
					generate
 | 
				
			||||||
 | 
						SigSpec C = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
						auto WIDTH = rng(3)+1;
 | 
				
			||||||
 | 
						SigSpec D = module->addWire(NEW_ID, WIDTH);
 | 
				
			||||||
 | 
						SigSpec Q = module->addWire(NEW_ID, WIDTH);
 | 
				
			||||||
 | 
						auto r = rng(8);
 | 
				
			||||||
 | 
						Cell *cell = nullptr;
 | 
				
			||||||
 | 
						switch (r)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							cell = module->addDff(NEW_ID, C, D, Q, r & 1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
						case 5:
 | 
				
			||||||
 | 
							//cell = module->addDffe(NEW_ID, C, module->addWire(NEW_ID), D, Q, r & 1, r & 4);
 | 
				
			||||||
 | 
							//break;
 | 
				
			||||||
 | 
						case 6:
 | 
				
			||||||
 | 
						case 7:
 | 
				
			||||||
 | 
							WIDTH = 1;
 | 
				
			||||||
 | 
							cell = module->addDffGate(NEW_ID, C, D[0], Q[0], r & 1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default: log_abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						shiftx->connections_.at(\A)[shiftx_width-1] = port(cell, \Q)[rng(WIDTH)];
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code clk_port en_port
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_))
 | 
				
			||||||
 | 
							clk_port = \C;
 | 
				
			||||||
 | 
						else if (first->type.in($dff, $dffe))
 | 
				
			||||||
 | 
							clk_port = \CLK;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
						if (first->type.in($_DFF_N_, $_DFF_P_, $dff))
 | 
				
			||||||
 | 
							en_port = IdString();
 | 
				
			||||||
 | 
						else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_))
 | 
				
			||||||
 | 
							en_port = \E;
 | 
				
			||||||
 | 
						else if (first->type.in($dffe))
 | 
				
			||||||
 | 
							en_port = \EN;
 | 
				
			||||||
 | 
						else log_abort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chain_bits.insert(port(first, \Q)[slice]);
 | 
				
			||||||
 | 
						chain.emplace_back(first, slice);
 | 
				
			||||||
 | 
						subpattern(tail);
 | 
				
			||||||
 | 
					finally
 | 
				
			||||||
 | 
						if (GetSize(chain) == shiftx_width)
 | 
				
			||||||
 | 
							accept;
 | 
				
			||||||
 | 
						chain.clear();
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subpattern tail
 | 
				
			||||||
 | 
					arg first
 | 
				
			||||||
 | 
					arg shiftx
 | 
				
			||||||
 | 
					arg shiftx_width
 | 
				
			||||||
 | 
					arg slice
 | 
				
			||||||
 | 
					arg clk_port
 | 
				
			||||||
 | 
					arg en_port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match next
 | 
				
			||||||
 | 
						semioptional
 | 
				
			||||||
 | 
						select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe)
 | 
				
			||||||
 | 
						select !next->has_keep_attr()
 | 
				
			||||||
 | 
						select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep)
 | 
				
			||||||
 | 
						slice idx GetSize(port(next, \Q))
 | 
				
			||||||
 | 
						select nusers(port(next, \Q)[idx]) <= 3
 | 
				
			||||||
 | 
						index <IdString> next->type === chain.back().first->type
 | 
				
			||||||
 | 
						index <SigBit> port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second]
 | 
				
			||||||
 | 
						index <SigBit> port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)]
 | 
				
			||||||
 | 
						filter port(next, clk_port) == port(first, clk_port)
 | 
				
			||||||
 | 
						filter en_port == IdString() || port(next, en_port) == port(first, en_port)
 | 
				
			||||||
 | 
						filter !next->type.in($dff, $dffe) || param(next, \CLK_POLARITY).as_bool() == param(first, \CLK_POLARITY).as_bool()
 | 
				
			||||||
 | 
						filter !next->type.in($dffe) || param(next, \EN_POLARITY).as_bool() == param(first, \EN_POLARITY).as_bool()
 | 
				
			||||||
 | 
						filter !chain_bits.count(port(next, \D)[idx])
 | 
				
			||||||
 | 
						set slice idx
 | 
				
			||||||
 | 
					generate
 | 
				
			||||||
 | 
						if (GetSize(chain) < shiftx_width) {
 | 
				
			||||||
 | 
							auto back = chain.back().first;
 | 
				
			||||||
 | 
							auto slice = chain.back().second;
 | 
				
			||||||
 | 
							if (back->type.in($dff, $dffe)) {
 | 
				
			||||||
 | 
								auto WIDTH = GetSize(port(back, \D));
 | 
				
			||||||
 | 
								if (rng(2) == 0 && slice < WIDTH-1) {
 | 
				
			||||||
 | 
									auto new_slice = slice + rng(WIDTH-1-slice);
 | 
				
			||||||
 | 
									back->connections_.at(\D)[slice] = port(back, \Q)[new_slice];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									auto D = module->addWire(NEW_ID, WIDTH);
 | 
				
			||||||
 | 
									if (back->type == $dff)
 | 
				
			||||||
 | 
										module->addDff(NEW_ID, port(back, \CLK), D, port(back, \D), param(back, \CLK_POLARITY).as_bool());
 | 
				
			||||||
 | 
									else if (back->type == $dffe)
 | 
				
			||||||
 | 
										module->addDffe(NEW_ID, port(back, \CLK), port(back, \EN), D, port(back, \D), param(back, \CLK_POLARITY).as_bool(), param(back, \EN_POLARITY).as_bool());
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										log_abort();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (back->type.begins_with("$_DFF_")) {
 | 
				
			||||||
 | 
								Cell *cell = module->addCell(NEW_ID, back->type);
 | 
				
			||||||
 | 
								cell->setPort(\C, back->getPort(\C));
 | 
				
			||||||
 | 
								cell->setPort(\D, module->addWire(NEW_ID));
 | 
				
			||||||
 | 
								cell->setPort(\Q, back->getPort(\D));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								log_abort();
 | 
				
			||||||
 | 
							shiftx->connections_.at(\A)[shiftx_width-1-GetSize(chain)] = port(back, \D)[slice];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					endmatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code
 | 
				
			||||||
 | 
						if (next) {
 | 
				
			||||||
 | 
							chain_bits.insert(port(next, \Q)[slice]);
 | 
				
			||||||
 | 
							chain.emplace_back(next, slice);
 | 
				
			||||||
 | 
							if (GetSize(chain) < shiftx_width)
 | 
				
			||||||
 | 
								subpattern(tail);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					endcode
 | 
				
			||||||
| 
						 | 
					@ -694,30 +694,27 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
				
			||||||
		int in_wires = 0, out_wires = 0;
 | 
							int in_wires = 0, out_wires = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Stitch in mapped_mod's inputs/outputs into module
 | 
							// Stitch in mapped_mod's inputs/outputs into module
 | 
				
			||||||
		for (auto &it : mapped_mod->wires_) {
 | 
							for (auto port : mapped_mod->ports) {
 | 
				
			||||||
			RTLIL::Wire *w = it.second;
 | 
								RTLIL::Wire *w = mapped_mod->wire(port);
 | 
				
			||||||
			if (!w->port_input && !w->port_output)
 | 
								RTLIL::Wire *wire = module->wire(port);
 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			RTLIL::Wire *wire = module->wire(w->name);
 | 
					 | 
				
			||||||
			log_assert(wire);
 | 
								log_assert(wire);
 | 
				
			||||||
			RTLIL::Wire *remap_wire = module->wire(remap_name(w->name));
 | 
								RTLIL::Wire *remap_wire = module->wire(remap_name(port));
 | 
				
			||||||
			RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
 | 
								RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
 | 
				
			||||||
			log_assert(GetSize(signal) >= GetSize(remap_wire));
 | 
								log_assert(GetSize(signal) >= GetSize(remap_wire));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			log_assert(w->port_input || w->port_output);
 | 
					 | 
				
			||||||
			RTLIL::SigSig conn;
 | 
								RTLIL::SigSig conn;
 | 
				
			||||||
			if (w->port_input) {
 | 
					 | 
				
			||||||
				conn.first = remap_wire;
 | 
					 | 
				
			||||||
				conn.second = signal;
 | 
					 | 
				
			||||||
				in_wires++;
 | 
					 | 
				
			||||||
				module->connect(conn);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (w->port_output) {
 | 
								if (w->port_output) {
 | 
				
			||||||
				conn.first = signal;
 | 
									conn.first = signal;
 | 
				
			||||||
				conn.second = remap_wire;
 | 
									conn.second = remap_wire;
 | 
				
			||||||
				out_wires++;
 | 
									out_wires++;
 | 
				
			||||||
				module->connect(conn);
 | 
									module->connect(conn);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								else if (w->port_input) {
 | 
				
			||||||
 | 
									conn.first = remap_wire;
 | 
				
			||||||
 | 
									conn.second = signal;
 | 
				
			||||||
 | 
									in_wires++;
 | 
				
			||||||
 | 
									module->connect(conn);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &it : bit_users)
 | 
							for (auto &it : bit_users)
 | 
				
			||||||
| 
						 | 
					@ -1300,9 +1297,6 @@ struct Abc9Pass : public Pass {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		assign_map.clear();
 | 
							assign_map.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// The "clean" pass also contains a design->check() call
 | 
					 | 
				
			||||||
		Pass::call(design, "clean");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		log_pop();
 | 
							log_pop();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} Abc9Pass;
 | 
					} Abc9Pass;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,9 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
 | 
				
			||||||
struct ShregmapTech
 | 
					struct ShregmapTech
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	virtual ~ShregmapTech() { }
 | 
						virtual ~ShregmapTech() { }
 | 
				
			||||||
	virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {}
 | 
						virtual bool analyze(vector<int> &taps) = 0;
 | 
				
			||||||
	virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {}
 | 
					 | 
				
			||||||
	virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) = 0;
 | 
					 | 
				
			||||||
	virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) = 0;
 | 
						virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +54,7 @@ struct ShregmapOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ShregmapTechGreenpak4 : ShregmapTech
 | 
					struct ShregmapTechGreenpak4 : ShregmapTech
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool analyze(vector<int> &taps, const vector<SigBit> &/*qbits*/)
 | 
						bool analyze(vector<int> &taps)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) {
 | 
							if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) {
 | 
				
			||||||
			taps.clear();
 | 
								taps.clear();
 | 
				
			||||||
| 
						 | 
					@ -93,155 +91,6 @@ struct ShregmapTechGreenpak4 : ShregmapTech
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ShregmapTechXilinx7 : ShregmapTech
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	dict<SigBit, std::tuple<Cell*,int,int>> sigbit_to_shiftx_offset;
 | 
					 | 
				
			||||||
	const ShregmapOptions &opts;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	virtual void init(const Module* module, const SigMap &sigmap) override
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		for (const auto &i : module->cells_) {
 | 
					 | 
				
			||||||
			auto cell = i.second;
 | 
					 | 
				
			||||||
			if (cell->type == ID($shiftx)) {
 | 
					 | 
				
			||||||
				if (cell->getParam(ID(Y_WIDTH)) != 1) continue;
 | 
					 | 
				
			||||||
				int j = 0;
 | 
					 | 
				
			||||||
				for (auto bit : sigmap(cell->getPort(ID::A)))
 | 
					 | 
				
			||||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0);
 | 
					 | 
				
			||||||
				log_assert(j == cell->getParam(ID(A_WIDTH)).as_int());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if (cell->type == ID($mux)) {
 | 
					 | 
				
			||||||
				int j = 0;
 | 
					 | 
				
			||||||
				for (auto bit : sigmap(cell->getPort(ID::A)))
 | 
					 | 
				
			||||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++);
 | 
					 | 
				
			||||||
				j = 0;
 | 
					 | 
				
			||||||
				for (auto bit : sigmap(cell->getPort(ID::B)))
 | 
					 | 
				
			||||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto it = sigbit_to_shiftx_offset.find(bit);
 | 
					 | 
				
			||||||
		if (it == sigbit_to_shiftx_offset.end())
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		if (cell) {
 | 
					 | 
				
			||||||
			if (cell->type == ID($shiftx) && port == ID::A)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			if (cell->type == ID($mux) && port.in(ID::A, ID::B))
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sigbit_to_shiftx_offset.erase(it);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) override
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (GetSize(taps) == 1)
 | 
					 | 
				
			||||||
			return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (taps.back() < opts.minlen-1)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Cell *shiftx = nullptr;
 | 
					 | 
				
			||||||
		int group = 0;
 | 
					 | 
				
			||||||
		for (int i = 0; i < GetSize(taps); ++i) {
 | 
					 | 
				
			||||||
			auto it = sigbit_to_shiftx_offset.find(qbits[i]);
 | 
					 | 
				
			||||||
			if (it == sigbit_to_shiftx_offset.end())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Check taps are sequential
 | 
					 | 
				
			||||||
			if (i != taps[i])
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			// Check taps are not connected to a shift register,
 | 
					 | 
				
			||||||
			// or sequential to the same shift register
 | 
					 | 
				
			||||||
			if (i == 0) {
 | 
					 | 
				
			||||||
				int offset;
 | 
					 | 
				
			||||||
				std::tie(shiftx,offset,group) = it->second;
 | 
					 | 
				
			||||||
				if (offset != i)
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				Cell *shiftx_ = std::get<0>(it->second);
 | 
					 | 
				
			||||||
				if (shiftx_ != shiftx)
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
				int offset = std::get<1>(it->second);
 | 
					 | 
				
			||||||
				if (offset != i)
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
				int group_ = std::get<2>(it->second);
 | 
					 | 
				
			||||||
				if (group_ != group)
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log_assert(shiftx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Only map if $shiftx exclusively covers the shift register
 | 
					 | 
				
			||||||
		if (shiftx->type == ID($shiftx)) {
 | 
					 | 
				
			||||||
			if (GetSize(taps) > shiftx->getParam(ID(A_WIDTH)).as_int())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			// Due to padding the most significant bits of A may be 1'bx,
 | 
					 | 
				
			||||||
			//   and if so, discount them
 | 
					 | 
				
			||||||
			if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) {
 | 
					 | 
				
			||||||
				const SigSpec A = shiftx->getPort(ID::A);
 | 
					 | 
				
			||||||
				const int A_width = shiftx->getParam(ID(A_WIDTH)).as_int();
 | 
					 | 
				
			||||||
				for (int i = GetSize(taps); i < A_width; ++i)
 | 
					 | 
				
			||||||
					if (A[i] != RTLIL::Sx) return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if (GetSize(taps) != shiftx->getParam(ID(A_WIDTH)).as_int())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (shiftx->type == ID($mux)) {
 | 
					 | 
				
			||||||
			if (GetSize(taps) != 2)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else log_abort();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) override
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &tap = *taps.begin();
 | 
					 | 
				
			||||||
		auto bit = tap.second;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto it = sigbit_to_shiftx_offset.find(bit);
 | 
					 | 
				
			||||||
		log_assert(it != sigbit_to_shiftx_offset.end());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto newcell = cell->module->addCell(NEW_ID, ID($__XILINX_SHREG_));
 | 
					 | 
				
			||||||
		newcell->set_src_attribute(cell->get_src_attribute());
 | 
					 | 
				
			||||||
		newcell->setParam(ID(DEPTH), cell->getParam(ID(DEPTH)));
 | 
					 | 
				
			||||||
		newcell->setParam(ID(INIT), cell->getParam(ID(INIT)));
 | 
					 | 
				
			||||||
		newcell->setParam(ID(CLKPOL), cell->getParam(ID(CLKPOL)));
 | 
					 | 
				
			||||||
		newcell->setParam(ID(ENPOL), cell->getParam(ID(ENPOL)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		newcell->setPort(ID(C), cell->getPort(ID(C)));
 | 
					 | 
				
			||||||
		newcell->setPort(ID(D), cell->getPort(ID(D)));
 | 
					 | 
				
			||||||
		if (cell->hasPort(ID(E)))
 | 
					 | 
				
			||||||
			newcell->setPort(ID(E), cell->getPort(ID(E)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Cell* shiftx = std::get<0>(it->second);
 | 
					 | 
				
			||||||
		RTLIL::SigSpec l_wire, q_wire;
 | 
					 | 
				
			||||||
		if (shiftx->type == ID($shiftx)) {
 | 
					 | 
				
			||||||
			l_wire = shiftx->getPort(ID::B);
 | 
					 | 
				
			||||||
			q_wire = shiftx->getPort(ID::Y);
 | 
					 | 
				
			||||||
			shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (shiftx->type == ID($mux)) {
 | 
					 | 
				
			||||||
			l_wire = shiftx->getPort(ID(S));
 | 
					 | 
				
			||||||
			q_wire = shiftx->getPort(ID::Y);
 | 
					 | 
				
			||||||
			shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else log_abort();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		newcell->setPort(ID(Q), q_wire);
 | 
					 | 
				
			||||||
		newcell->setPort(ID(L), l_wire);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ShregmapWorker
 | 
					struct ShregmapWorker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Module *module;
 | 
						Module *module;
 | 
				
			||||||
| 
						 | 
					@ -264,10 +113,8 @@ struct ShregmapWorker
 | 
				
			||||||
		for (auto wire : module->wires())
 | 
							for (auto wire : module->wires())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
 | 
								if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
 | 
				
			||||||
				for (auto bit : sigmap(wire)) {
 | 
									for (auto bit : sigmap(wire))
 | 
				
			||||||
					sigbit_with_non_chain_users.insert(bit);
 | 
										sigbit_with_non_chain_users.insert(bit);
 | 
				
			||||||
					if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {});
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (wire->attributes.count(ID(init))) {
 | 
								if (wire->attributes.count(ID(init))) {
 | 
				
			||||||
| 
						 | 
					@ -317,10 +164,8 @@ struct ShregmapWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto conn : cell->connections())
 | 
								for (auto conn : cell->connections())
 | 
				
			||||||
				if (cell->input(conn.first))
 | 
									if (cell->input(conn.first))
 | 
				
			||||||
					for (auto bit : sigmap(conn.second)) {
 | 
										for (auto bit : sigmap(conn.second))
 | 
				
			||||||
						sigbit_with_non_chain_users.insert(bit);
 | 
											sigbit_with_non_chain_users.insert(bit);
 | 
				
			||||||
						if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,7 +191,7 @@ struct ShregmapWorker
 | 
				
			||||||
				IdString q_port = opts.ffcells.at(c1->type).second;
 | 
									IdString q_port = opts.ffcells.at(c1->type).second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				auto c1_conn = c1->connections();
 | 
									auto c1_conn = c1->connections();
 | 
				
			||||||
				auto c2_conn = c1->connections();
 | 
									auto c2_conn = c2->connections();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				c1_conn.erase(d_port);
 | 
									c1_conn.erase(d_port);
 | 
				
			||||||
				c1_conn.erase(q_port);
 | 
									c1_conn.erase(q_port);
 | 
				
			||||||
| 
						 | 
					@ -425,7 +270,7 @@ struct ShregmapWorker
 | 
				
			||||||
					if (taps.empty() || taps.back() < depth-1)
 | 
										if (taps.empty() || taps.back() < depth-1)
 | 
				
			||||||
						taps.push_back(depth-1);
 | 
											taps.push_back(depth-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (opts.tech->analyze(taps, qbits))
 | 
										if (opts.tech->analyze(taps))
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					taps.pop_back();
 | 
										taps.pop_back();
 | 
				
			||||||
| 
						 | 
					@ -544,9 +389,6 @@ struct ShregmapWorker
 | 
				
			||||||
	ShregmapWorker(Module *module, const ShregmapOptions &opts) :
 | 
						ShregmapWorker(Module *module, const ShregmapOptions &opts) :
 | 
				
			||||||
			module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
 | 
								module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (opts.tech)
 | 
					 | 
				
			||||||
			opts.tech->init(module, sigmap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		make_sigbit_chain_next_prev();
 | 
							make_sigbit_chain_next_prev();
 | 
				
			||||||
		find_chain_start_cells();
 | 
							find_chain_start_cells();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -617,11 +459,6 @@ struct ShregmapPass : public Pass {
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -tech greenpak4\n");
 | 
							log("    -tech greenpak4\n");
 | 
				
			||||||
		log("        map to greenpak4 shift registers.\n");
 | 
							log("        map to greenpak4 shift registers.\n");
 | 
				
			||||||
		log("        this option also implies -clkpol pos -zinit\n");
 | 
					 | 
				
			||||||
		log("\n");
 | 
					 | 
				
			||||||
		log("    -tech xilinx\n");
 | 
					 | 
				
			||||||
		log("        map to xilinx dynamic-length shift registers.\n");
 | 
					 | 
				
			||||||
		log("        this option also implies -params -init\n");
 | 
					 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
| 
						 | 
					@ -676,12 +513,6 @@ struct ShregmapPass : public Pass {
 | 
				
			||||||
					clkpol = "pos";
 | 
										clkpol = "pos";
 | 
				
			||||||
					opts.zinit = true;
 | 
										opts.zinit = true;
 | 
				
			||||||
					opts.tech = new ShregmapTechGreenpak4;
 | 
										opts.tech = new ShregmapTechGreenpak4;
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else if (tech == "xilinx") {
 | 
					 | 
				
			||||||
					opts.init = true;
 | 
					 | 
				
			||||||
					opts.params = true;
 | 
					 | 
				
			||||||
					enpol = "any_or_none";
 | 
					 | 
				
			||||||
					opts.tech = new ShregmapTechXilinx7(opts);
 | 
					 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					argidx--;
 | 
										argidx--;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,8 @@
 | 
				
			||||||
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
 | 
					OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
 | 
				
			||||||
        techlibs/ecp5/ecp5_gsr.o
 | 
					        techlibs/ecp5/ecp5_gsr.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_ff.vh))
 | 
				
			||||||
 | 
					$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_io.vh))
 | 
				
			||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
 | 
					$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
 | 
					$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v))
 | 
					$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								techlibs/ecp5/cells_ff.vh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								techlibs/ecp5/cells_ff.vh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					// Diamond flip-flops
 | 
				
			||||||
 | 
					module FD1P3AX(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),  .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1P3AY(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),  .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3AX(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),           .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3AY(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),           .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3BX(input PD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD),          .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3DX(input CD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD),          .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3IX(input CD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD),          .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					module FD1S3JX(input PD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD),          .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Diamond latches
 | 
				
			||||||
 | 
					// module FL1P3AY(); endmodule
 | 
				
			||||||
 | 
					// module FL1P3AZ(); endmodule
 | 
				
			||||||
 | 
					// module FL1P3BX(); endmodule
 | 
				
			||||||
 | 
					// module FL1P3DX(); endmodule
 | 
				
			||||||
 | 
					// module FL1P3IY(); endmodule
 | 
				
			||||||
 | 
					// module FL1P3JY(); endmodule
 | 
				
			||||||
 | 
					// module FL1S3AX(); endmodule
 | 
				
			||||||
 | 
					// 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 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Diamond I/O latches
 | 
				
			||||||
 | 
					// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
 | 
				
			||||||
 | 
					// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
 | 
				
			||||||
 | 
					// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
 | 
				
			||||||
 | 
					// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
 | 
				
			||||||
							
								
								
									
										14
									
								
								techlibs/ecp5/cells_io.vh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								techlibs/ecp5/cells_io.vh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					// Diamond I/O buffers
 | 
				
			||||||
 | 
					module IB   (input I,     output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
				
			||||||
 | 
					module IBPU (input I,     output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
				
			||||||
 | 
					module IBPD (input I,     output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
				
			||||||
 | 
					module OB   (input I,     output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule
 | 
				
			||||||
 | 
					module OBZ  (input I, T,  output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
				
			||||||
 | 
					module OBZPU(input I, T,  output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
				
			||||||
 | 
					module OBZPD(input I, T,  output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
				
			||||||
 | 
					module OBCO (input I,     output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule
 | 
				
			||||||
 | 
					module BB   (input I, T,  output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
				
			||||||
 | 
					module BBPU (input I, T,  output O, inout B); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
				
			||||||
 | 
					module BBPD (input I, T,  output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
				
			||||||
 | 
					module ILVDS(input A, AN, output Z    ); TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule
 | 
				
			||||||
 | 
					module OLVDS(input A,     output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule
 | 
				
			||||||
| 
						 | 
					@ -47,59 +47,8 @@ module  \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .
 | 
				
			||||||
module  \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 | 
					module  \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
module  \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 | 
					module  \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Diamond flip-flops
 | 
					`include "cells_ff.vh"
 | 
				
			||||||
// module FD1P3AX(); endmodule
 | 
					`include "cells_io.vh"
 | 
				
			||||||
// module FD1P3AY(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3BX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3DX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3IX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3JX(); endmodule
 | 
					 | 
				
			||||||
// module FD1S3AX(); endmodule
 | 
					 | 
				
			||||||
// module FD1S3AY(); endmodule
 | 
					 | 
				
			||||||
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
// module FL1P3AY(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3AZ(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3BX(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3DX(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3IY(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3JY(); endmodule
 | 
					 | 
				
			||||||
// module FL1S3AX(); endmodule
 | 
					 | 
				
			||||||
// module FL1S3AY(); endmodule
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Diamond I/O buffers
 | 
					 | 
				
			||||||
module IB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
					 | 
				
			||||||
module IBPU (input I, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("INPUT"))   _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
					 | 
				
			||||||
module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
 | 
					 | 
				
			||||||
module OB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule
 | 
					 | 
				
			||||||
module OBZ  (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBZPU(input I, T, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("OUTPUT"))   _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule
 | 
					 | 
				
			||||||
module BB   (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module BBPU (input I, T, output O, inout B); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("BIDIR"))   _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule
 | 
					 | 
				
			||||||
module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Diamond I/O registers
 | 
					 | 
				
			||||||
module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .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
 | 
					 | 
				
			||||||
// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
`ifndef NO_LUT
 | 
					`ifndef NO_LUT
 | 
				
			||||||
module \$lut (A, Y);
 | 
					module \$lut (A, Y);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,14 +229,15 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
 | 
				
			||||||
	parameter REGSET = "RESET";
 | 
						parameter REGSET = "RESET";
 | 
				
			||||||
	parameter [127:0] LSRMODE = "LSR";
 | 
						parameter [127:0] LSRMODE = "LSR";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg muxce;
 | 
						wire muxce;
 | 
				
			||||||
	always @(*)
 | 
						generate
 | 
				
			||||||
		case (CEMUX)
 | 
							case (CEMUX)
 | 
				
			||||||
			"1": muxce = 1'b1;
 | 
								"1": assign muxce = 1'b1;
 | 
				
			||||||
			"0": muxce = 1'b0;
 | 
								"0": assign muxce = 1'b0;
 | 
				
			||||||
			"INV": muxce = ~CE;
 | 
								"INV": assign muxce = ~CE;
 | 
				
			||||||
			default: muxce = CE;
 | 
								default: assign muxce = CE;
 | 
				
			||||||
		endcase
 | 
							endcase
 | 
				
			||||||
 | 
						endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
 | 
						wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
 | 
				
			||||||
	wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
 | 
						wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
 | 
				
			||||||
| 
						 | 
					@ -693,56 +694,9 @@ module DP16KD(
 | 
				
			||||||
	parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
 | 
						parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Diamond flip-flops
 | 
					`ifndef NO_INCLUDES
 | 
				
			||||||
// module FD1P3AX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3AY(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3BX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3DX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3IX(); endmodule
 | 
					 | 
				
			||||||
// module FD1P3JX(); endmodule
 | 
					 | 
				
			||||||
// module FD1S3AX(); endmodule
 | 
					 | 
				
			||||||
// module FD1S3AY(); endmodule
 | 
					 | 
				
			||||||
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
// module FL1P3AY(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3AZ(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3BX(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3DX(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3IY(); endmodule
 | 
					 | 
				
			||||||
// module FL1P3JY(); endmodule
 | 
					 | 
				
			||||||
// module FL1S3AX(); endmodule
 | 
					 | 
				
			||||||
// module FL1S3AY(); endmodule
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Diamond I/O buffers
 | 
					`include "cells_ff.vh"
 | 
				
			||||||
module IB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
 | 
					`include "cells_io.vh"
 | 
				
			||||||
module IBPU (input I, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("INPUT"))   tio (.B(I), .O(O)); endmodule
 | 
					 | 
				
			||||||
module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
 | 
					 | 
				
			||||||
module OB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I)); endmodule
 | 
					 | 
				
			||||||
module OBZ  (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBZPU(input I, T, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("OUTPUT"))   tio (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
 | 
					 | 
				
			||||||
module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule
 | 
					 | 
				
			||||||
module BB   (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module BBPU (input I, T, output O, inout B); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("BIDIR"))   tio (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
 | 
					 | 
				
			||||||
module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT"))  tio (.B(A), .O(Z)); endmodule
 | 
					 | 
				
			||||||
module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Diamond I/O registers
 | 
					`endif
 | 
				
			||||||
module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
 | 
					 | 
				
			||||||
module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  tff (.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
 | 
					 | 
				
			||||||
// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ struct Ecp5GsrPass : public Pass {
 | 
				
			||||||
				SigBit lsr = sigmap(sig_lsr[0]);
 | 
									SigBit lsr = sigmap(sig_lsr[0]);
 | 
				
			||||||
				if (!inverted_gsr.count(lsr))
 | 
									if (!inverted_gsr.count(lsr))
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				cell->setParam(ID(SRMODE), Const("SYNC"));
 | 
									cell->setParam(ID(SRMODE), Const("LSR_OVER_CE"));
 | 
				
			||||||
				cell->unsetPort(ID(LSR));
 | 
									cell->unsetPort(ID(LSR));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								techlibs/ecp5/tests/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								techlibs/ecp5/tests/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					work_*
 | 
				
			||||||
							
								
								
									
										82
									
								
								techlibs/ecp5/tests/test_diamond_ffs.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								techlibs/ecp5/tests/test_diamond_ffs.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if not os.path.exists("work_ff"):
 | 
				
			||||||
 | 
						os.mkdir("work_ff")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					modules = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					with open("../cells_ff.vh", "r") as f:
 | 
				
			||||||
 | 
						with open("work_ff/cells_ff_gate.v", "w") as g:
 | 
				
			||||||
 | 
							for line in f:
 | 
				
			||||||
 | 
								if not line.startswith("module"):
 | 
				
			||||||
 | 
									g.write(line)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								else:
 | 
				
			||||||
 | 
									spidx = line.find(" ")
 | 
				
			||||||
 | 
									bridx = line.find("(")
 | 
				
			||||||
 | 
									modname = line[spidx+1 : bridx]
 | 
				
			||||||
 | 
									g.write("module %s_gate" % modname)
 | 
				
			||||||
 | 
									g.write(line[bridx:])
 | 
				
			||||||
 | 
									inpidx = line.find("input ")
 | 
				
			||||||
 | 
									outpidx = line.find(", output")
 | 
				
			||||||
 | 
									modules.append((modname, [x.strip() for x in line[inpidx+6:outpidx].split(",")]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					with open("work_ff/testbench.v", "w") as f:
 | 
				
			||||||
 | 
						print("""
 | 
				
			||||||
 | 
					`timescale 1ns/ 1ps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module testbench;
 | 
				
			||||||
 | 
					reg pur = 0, clk, rst, cen, d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Needed for Diamond sim models
 | 
				
			||||||
 | 
					GSR GSR_INST (.GSR(1'b1));
 | 
				
			||||||
 | 
					PUR PUR_INST (.PUR(pur));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					initial begin
 | 
				
			||||||
 | 
						$dumpfile("work_ff/ffs.vcd");
 | 
				
			||||||
 | 
						$dumpvars(0, testbench);
 | 
				
			||||||
 | 
						#5;
 | 
				
			||||||
 | 
						pur = 1;
 | 
				
			||||||
 | 
						#95;
 | 
				
			||||||
 | 
						repeat (2500) begin
 | 
				
			||||||
 | 
							{clk, rst, cen, d} = $random;
 | 
				
			||||||
 | 
							#10;
 | 
				
			||||||
 | 
							check_outputs;
 | 
				
			||||||
 | 
							#1;
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
						$finish;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
						""", file=f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for modname, inputs in modules:
 | 
				
			||||||
 | 
							print("    wire %s_gold_q, %s_gate_q;"  % (modname, modname), file=f)
 | 
				
			||||||
 | 
							portconns = []
 | 
				
			||||||
 | 
							for inp in inputs:
 | 
				
			||||||
 | 
								if inp in ("SCLK", "CK"):
 | 
				
			||||||
 | 
									portconns.append(".%s(clk)" % inp)
 | 
				
			||||||
 | 
								elif inp in ("CD", "PD"):
 | 
				
			||||||
 | 
									portconns.append(".%s(rst)" % inp)
 | 
				
			||||||
 | 
								elif inp == "SP":
 | 
				
			||||||
 | 
									portconns.append(".%s(cen)" % inp)
 | 
				
			||||||
 | 
								elif inp == "D":
 | 
				
			||||||
 | 
									portconns.append(".%s(d)" % inp)
 | 
				
			||||||
 | 
								else:
 | 
				
			||||||
 | 
									assert False
 | 
				
			||||||
 | 
							portconns.append(".Q(%s_gold_q)" % modname)
 | 
				
			||||||
 | 
							print("    %s %s_gold_i (%s);" % (modname, modname, ", ".join(portconns)), file=f)
 | 
				
			||||||
 | 
							portconns[-1] = (".Q(%s_gate_q)" % modname)
 | 
				
			||||||
 | 
							print("    %s_gate %s_gate_i (%s);" % (modname, modname, ", ".join(portconns)), file=f)
 | 
				
			||||||
 | 
							print("", file=f)
 | 
				
			||||||
 | 
						print("    task check_outputs;", file=f)
 | 
				
			||||||
 | 
						print("        begin", file=f)
 | 
				
			||||||
 | 
						print("             if (%s_gold_q != %s_gate_q) $display(\"MISMATCH at %%1t:  %s_gold_q=%%b, %s_gate_q=%%b\", $time, %s_gold_q, %s_gate_q);" %
 | 
				
			||||||
 | 
								(modname, modname, modname, modname, modname, modname), file=f)
 | 
				
			||||||
 | 
						print("        end", file=f)
 | 
				
			||||||
 | 
						print("    endtask", file=f)
 | 
				
			||||||
 | 
						print("endmodule", file=f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					diamond_models = "/usr/local/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u"
 | 
				
			||||||
 | 
					subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim.v", "work_ff/testbench.v"])
 | 
				
			||||||
 | 
					subprocess.call(["vvp", "work_ff/testbench"])
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,11 @@
 | 
				
			||||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
					# NB: Inputs/Outputs must be ordered alphabetically
 | 
				
			||||||
#     (with exceptions for carry in/out)
 | 
					#     (with exceptions for carry in/out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Inputs: A B CI
 | 
					# Inputs: A B I0 I3 CI
 | 
				
			||||||
# Outputs: O CO
 | 
					# Outputs: O CO
 | 
				
			||||||
#   (NB: carry chain input/output must be last
 | 
					#   (NB: carry chain input/output must be last
 | 
				
			||||||
#        input/output and have been moved there
 | 
					#        input/output and have been moved there
 | 
				
			||||||
#        overriding the alphabetical ordering)
 | 
					#        overriding the alphabetical ordering)
 | 
				
			||||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
					$__ICE40_CARRY_WRAPPER 1 1 5 2
 | 
				
			||||||
400 379 316
 | 
					400 379 449 316 316
 | 
				
			||||||
259 231 126
 | 
					259 231 -   -   126
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,11 @@
 | 
				
			||||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
					# NB: Inputs/Outputs must be ordered alphabetically
 | 
				
			||||||
#     (with exceptions for carry in/out)
 | 
					#     (with exceptions for carry in/out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Inputs: A B CI
 | 
					# Inputs: A B I0 I3 CI
 | 
				
			||||||
# Outputs: O CO
 | 
					# Outputs: O CO
 | 
				
			||||||
#   (NB: carry chain input/output must be last
 | 
					#   (NB: carry chain input/output must be last
 | 
				
			||||||
#        input/output and have been moved there
 | 
					#        input/output and have been moved there
 | 
				
			||||||
#        overriding the alphabetical ordering)
 | 
					#        overriding the alphabetical ordering)
 | 
				
			||||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
					$__ICE40_CARRY_WRAPPER 1 1 5 2
 | 
				
			||||||
589 558 465
 | 
					589 558 661 465 465
 | 
				
			||||||
675 609 186 
 | 
					675 609 -   -   186
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,11 @@
 | 
				
			||||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
					# NB: Inputs/Outputs must be ordered alphabetically
 | 
				
			||||||
#     (with exceptions for carry in/out)
 | 
					#     (with exceptions for carry in/out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Inputs: A B CI
 | 
					# Inputs: A B I0 I3 CI
 | 
				
			||||||
# Outputs: O CO
 | 
					# Outputs: O CO
 | 
				
			||||||
#   (NB: carry chain input/output must be last
 | 
					#   (NB: carry chain input/output must be last
 | 
				
			||||||
#        input/output and have been moved there
 | 
					#        input/output and have been moved there
 | 
				
			||||||
#        overriding the alphabetical ordering)
 | 
					#        overriding the alphabetical ordering)
 | 
				
			||||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
					$__ICE40_CARRY_WRAPPER 1 1 5 2
 | 
				
			||||||
1231 1205 874
 | 
					1231 1205 1285 874 874
 | 
				
			||||||
675  609  278
 | 
					675  609  -    -   278
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,15 +142,16 @@ module SB_CARRY (output CO, input I0, I1, CI);
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(* abc_box_id = 1, lib_whitebox *)
 | 
					(* abc_box_id = 1, lib_whitebox *)
 | 
				
			||||||
module \$__ICE40_FULL_ADDER (
 | 
					module \$__ICE40_CARRY_WRAPPER (
 | 
				
			||||||
	(* abc_carry *)
 | 
						(* abc_carry *)
 | 
				
			||||||
	output CO,
 | 
						output CO,
 | 
				
			||||||
	output O,
 | 
						output O,
 | 
				
			||||||
	input A,
 | 
						input A, B,
 | 
				
			||||||
	input B,
 | 
					 | 
				
			||||||
	(* abc_carry *)
 | 
						(* abc_carry *)
 | 
				
			||||||
	input CI
 | 
						input CI,
 | 
				
			||||||
 | 
						input I0, I3
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
						parameter LUT = 0;
 | 
				
			||||||
	SB_CARRY carry (
 | 
						SB_CARRY carry (
 | 
				
			||||||
		.I0(A),
 | 
							.I0(A),
 | 
				
			||||||
		.I1(B),
 | 
							.I1(B),
 | 
				
			||||||
| 
						 | 
					@ -158,16 +159,12 @@ module \$__ICE40_FULL_ADDER (
 | 
				
			||||||
		.CO(CO)
 | 
							.CO(CO)
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
	SB_LUT4 #(
 | 
						SB_LUT4 #(
 | 
				
			||||||
		//         I0: 1010 1010 1010 1010
 | 
							.LUT_INIT(LUT)
 | 
				
			||||||
		//         I1: 1100 1100 1100 1100
 | 
					 | 
				
			||||||
		//         I2: 1111 0000 1111 0000
 | 
					 | 
				
			||||||
		//         I3: 1111 1111 0000 0000
 | 
					 | 
				
			||||||
		.LUT_INIT(16'b 0110_1001_1001_0110)
 | 
					 | 
				
			||||||
	) adder (
 | 
						) adder (
 | 
				
			||||||
		.I0(1'b0),
 | 
							.I0(I0),
 | 
				
			||||||
		.I1(A),
 | 
							.I1(A),
 | 
				
			||||||
		.I2(B),
 | 
							.I2(B),
 | 
				
			||||||
		.I3(CI),
 | 
							.I3(I3),
 | 
				
			||||||
		.O(O)
 | 
							.O(O)
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ static void run_ice40_opts(Module *module)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (cell->type == "$__ICE40_FULL_ADDER")
 | 
							if (cell->type == "$__ICE40_CARRY_WRAPPER")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			SigSpec non_const_inputs, replacement_output;
 | 
								SigSpec non_const_inputs, replacement_output;
 | 
				
			||||||
			int count_zeros = 0, count_ones = 0;
 | 
								int count_zeros = 0, count_ones = 0;
 | 
				
			||||||
| 
						 | 
					@ -114,16 +114,17 @@ static void run_ice40_opts(Module *module)
 | 
				
			||||||
				optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
 | 
									optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
 | 
				
			||||||
				module->connect(cell->getPort("\\CO")[0], replacement_output);
 | 
									module->connect(cell->getPort("\\CO")[0], replacement_output);
 | 
				
			||||||
				module->design->scratchpad_set_bool("opt.did_something", true);
 | 
									module->design->scratchpad_set_bool("opt.did_something", true);
 | 
				
			||||||
				log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
 | 
									log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
 | 
				
			||||||
						log_id(module), log_id(cell), log_signal(replacement_output));
 | 
											log_id(module), log_id(cell), log_signal(replacement_output));
 | 
				
			||||||
				cell->type = "$lut";
 | 
									cell->type = "$lut";
 | 
				
			||||||
				cell->setPort("\\A", { State::S0, inbit[0], inbit[1], inbit[2] });
 | 
									cell->setPort("\\A", { cell->getPort("\\I0"), inbit[0], inbit[1], cell->getPort("\\I3") });
 | 
				
			||||||
				cell->setPort("\\Y", cell->getPort("\\O"));
 | 
									cell->setPort("\\Y", cell->getPort("\\O"));
 | 
				
			||||||
				cell->unsetPort("\\B");
 | 
									cell->unsetPort("\\B");
 | 
				
			||||||
				cell->unsetPort("\\CI");
 | 
									cell->unsetPort("\\CI");
 | 
				
			||||||
 | 
									cell->unsetPort("\\I0");
 | 
				
			||||||
 | 
									cell->unsetPort("\\I3");
 | 
				
			||||||
				cell->unsetPort("\\CO");
 | 
									cell->unsetPort("\\CO");
 | 
				
			||||||
				cell->unsetPort("\\O");
 | 
									cell->unsetPort("\\O");
 | 
				
			||||||
				cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110"));
 | 
					 | 
				
			||||||
				cell->setParam("\\WIDTH", 4);
 | 
									cell->setParam("\\WIDTH", 4);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -303,9 +303,8 @@ struct SynthXilinxPass : public ScriptPass
 | 
				
			||||||
			if (widemux > 0 || help_mode)
 | 
								if (widemux > 0 || help_mode)
 | 
				
			||||||
				run("muxpack", "    ('-widemux' only)");
 | 
									run("muxpack", "    ('-widemux' only)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// shregmap -tech xilinx can cope with $shiftx and $mux
 | 
								// xilinx_srl looks for $shiftx cells for identifying variable-length
 | 
				
			||||||
			//   cells for identifying variable-length shift registers,
 | 
								//   shift registers, so attempt to convert $pmux-es to this
 | 
				
			||||||
			//   so attempt to convert $pmux-es to the former
 | 
					 | 
				
			||||||
			// Also: wide multiplexer inference benefits from this too
 | 
								// Also: wide multiplexer inference benefits from this too
 | 
				
			||||||
			if (!(nosrl && widemux == 0) || help_mode) {
 | 
								if (!(nosrl && widemux == 0) || help_mode) {
 | 
				
			||||||
				run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
 | 
									run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
 | 
				
			||||||
| 
						 | 
					@ -387,13 +386,8 @@ struct SynthXilinxPass : public ScriptPass
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			run("opt -full");
 | 
								run("opt -full");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!nosrl || help_mode) {
 | 
								if (!nosrl || help_mode)
 | 
				
			||||||
				// shregmap operates on bit-level flops, not word-level,
 | 
									run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')");
 | 
				
			||||||
				//   so break those down here
 | 
					 | 
				
			||||||
				run("simplemap t:$dff t:$dffe", "       (skip if '-nosrl')");
 | 
					 | 
				
			||||||
				// shregmap with '-tech xilinx' infers variable length shift regs
 | 
					 | 
				
			||||||
				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string techmap_args = " -map +/techmap.v";
 | 
								std::string techmap_args = " -map +/techmap.v";
 | 
				
			||||||
			if (help_mode)
 | 
								if (help_mode)
 | 
				
			||||||
| 
						 | 
					@ -421,6 +415,14 @@ struct SynthXilinxPass : public ScriptPass
 | 
				
			||||||
			run("clean");
 | 
								run("clean");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (check_label("map_ffs")) {
 | 
				
			||||||
 | 
									if (abc9 || help_mode) {
 | 
				
			||||||
 | 
											run("techmap -map +/xilinx/ff_map.v", "('-abc9' only)");
 | 
				
			||||||
 | 
											run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
 | 
				
			||||||
 | 
															"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "('-abc9' only)");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (check_label("map_luts")) {
 | 
							if (check_label("map_luts")) {
 | 
				
			||||||
			run("opt_expr -mux_undef");
 | 
								run("opt_expr -mux_undef");
 | 
				
			||||||
			if (flatten_before_abc)
 | 
								if (flatten_before_abc)
 | 
				
			||||||
| 
						 | 
					@ -446,10 +448,17 @@ struct SynthXilinxPass : public ScriptPass
 | 
				
			||||||
			// This shregmap call infers fixed length shift registers after abc
 | 
								// This shregmap call infers fixed length shift registers after abc
 | 
				
			||||||
			//   has performed any necessary retiming
 | 
								//   has performed any necessary retiming
 | 
				
			||||||
			if (!nosrl || help_mode)
 | 
								if (!nosrl || help_mode)
 | 
				
			||||||
				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
 | 
									run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')");
 | 
				
			||||||
			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
 | 
					
 | 
				
			||||||
			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
 | 
								std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";
 | 
				
			||||||
					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
 | 
								if (help_mode)
 | 
				
			||||||
 | 
										techmap_args += " [-map +/xilinx/ff_map.v]";
 | 
				
			||||||
 | 
								else if (!abc9)
 | 
				
			||||||
 | 
										techmap_args += " -map +/xilinx/ff_map.v";
 | 
				
			||||||
 | 
								run("techmap " + techmap_args);
 | 
				
			||||||
 | 
								if (!abc9)
 | 
				
			||||||
 | 
									run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
 | 
				
			||||||
 | 
											"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "(without '-abc9' only)");
 | 
				
			||||||
			run("clean");
 | 
								run("clean");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								tests/ice40/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/ice40/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					/run-test.mk
 | 
				
			||||||
 | 
					+*_synth.v
 | 
				
			||||||
 | 
					+*_testbench
 | 
				
			||||||
							
								
								
									
										13
									
								
								tests/ice40/add_sub.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/ice40/add_sub.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										9
									
								
								tests/ice40/add_sub.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/ice40/add_sub.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					read_verilog add_sub.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 11 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-count 6 t:SB_CARRY
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										91
									
								
								tests/ice40/adffs.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tests/ice40/adffs.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,91 @@
 | 
				
			||||||
 | 
					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 dffsr
 | 
				
			||||||
 | 
					    ( input d, clk, pre, clr, output reg q );
 | 
				
			||||||
 | 
					    initial begin
 | 
				
			||||||
 | 
					      q = 0;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
						always @( posedge clk, posedge pre, posedge clr )
 | 
				
			||||||
 | 
							if ( clr )
 | 
				
			||||||
 | 
								q <= 1'b0;
 | 
				
			||||||
 | 
							else if ( pre )
 | 
				
			||||||
 | 
								q <= 1'b1;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
					            q <= d;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module ndffnsnr
 | 
				
			||||||
 | 
					    ( input d, clk, pre, clr, output reg q );
 | 
				
			||||||
 | 
					    initial begin
 | 
				
			||||||
 | 
					      q = 0;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
						always @( negedge clk, negedge pre, negedge clr )
 | 
				
			||||||
 | 
							if ( !clr )
 | 
				
			||||||
 | 
								q <= 1'b0;
 | 
				
			||||||
 | 
							else if ( !pre )
 | 
				
			||||||
 | 
								q <= 1'b1;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
					            q <= d;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
					input clk,
 | 
				
			||||||
 | 
					input clr,
 | 
				
			||||||
 | 
					input pre,
 | 
				
			||||||
 | 
					input a,
 | 
				
			||||||
 | 
					output b,b1,b2,b3
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dffsr u_dffsr (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .clr (clr),
 | 
				
			||||||
 | 
					        .pre (pre),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ndffnsnr u_ndffnsnr (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .clr (clr),
 | 
				
			||||||
 | 
					        .pre (pre),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b1 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					adff u_adff (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .clr (clr),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b2 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					adffn u_adffn (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .clr (clr),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b3 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										12
									
								
								tests/ice40/adffs.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/ice40/adffs.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					read_verilog adffs.v
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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:SB_DFF
 | 
				
			||||||
 | 
					select -assert-count 1 t:SB_DFFN
 | 
				
			||||||
 | 
					select -assert-count 2 t:SB_DFFSR
 | 
				
			||||||
 | 
					select -assert-count 7 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_DFF t:SB_DFFN t:SB_DFFSR t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										19
									
								
								tests/ice40/alu.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/ice40/alu.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
						input clock,
 | 
				
			||||||
 | 
						input [31:0] dinA, dinB,
 | 
				
			||||||
 | 
						input [2:0] opcode,
 | 
				
			||||||
 | 
						output reg [31:0] dout
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						always @(posedge clock) begin
 | 
				
			||||||
 | 
							case (opcode)
 | 
				
			||||||
 | 
							0: dout <= dinA + dinB;
 | 
				
			||||||
 | 
							1: dout <= dinA - dinB;
 | 
				
			||||||
 | 
							2: dout <= dinA >> dinB;
 | 
				
			||||||
 | 
							3: dout <= $signed(dinA) >>> dinB;
 | 
				
			||||||
 | 
							4: dout <= dinA << dinB;
 | 
				
			||||||
 | 
							5: dout <= dinA & dinB;
 | 
				
			||||||
 | 
							6: dout <= dinA | dinB;
 | 
				
			||||||
 | 
							7: dout <= dinA ^ dinB;
 | 
				
			||||||
 | 
							endcase
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										11
									
								
								tests/ice40/alu.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/ice40/alu.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					read_verilog alu.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 62 t:SB_CARRY
 | 
				
			||||||
 | 
					select -assert-count 32 t:SB_DFF
 | 
				
			||||||
 | 
					select -assert-count 655 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_CARRY t:SB_DFF t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										17
									
								
								tests/ice40/counter.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/ice40/counter.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					module top    (
 | 
				
			||||||
 | 
					out,
 | 
				
			||||||
 | 
					clk,
 | 
				
			||||||
 | 
					reset
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					    output [7:0] out;
 | 
				
			||||||
 | 
					    input clk, reset;
 | 
				
			||||||
 | 
					    reg [7:0] out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    always @(posedge clk, posedge reset)
 | 
				
			||||||
 | 
							if (reset) begin
 | 
				
			||||||
 | 
								out <= 8'b0 ;
 | 
				
			||||||
 | 
							end else
 | 
				
			||||||
 | 
								out <= out + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										11
									
								
								tests/ice40/counter.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/ice40/counter.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					read_verilog counter.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -map +/ice40/cells_sim.v synth_ice40 # 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 6 t:SB_CARRY
 | 
				
			||||||
 | 
					select -assert-count 8 t:SB_DFFR
 | 
				
			||||||
 | 
					select -assert-count 8 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_CARRY t:SB_DFFR t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										37
									
								
								tests/ice40/dffs.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/ice40/dffs.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
					input clk,
 | 
				
			||||||
 | 
					input en,
 | 
				
			||||||
 | 
					input a,
 | 
				
			||||||
 | 
					output b,b1,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dff u_dff (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dffe u_ndffe (
 | 
				
			||||||
 | 
					        .clk (clk ),
 | 
				
			||||||
 | 
					        .en (en),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b1 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										10
									
								
								tests/ice40/dffs.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/ice40/dffs.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					read_verilog dffs.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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:SB_DFF
 | 
				
			||||||
 | 
					select -assert-count 1 t:SB_DFFE
 | 
				
			||||||
 | 
					select -assert-none t:SB_DFF t:SB_DFFE %% t:* %D
 | 
				
			||||||
							
								
								
									
										13
									
								
								tests/ice40/div_mod.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/ice40/div_mod.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										9
									
								
								tests/ice40/div_mod.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/ice40/div_mod.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					read_verilog div_mod.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 62 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-count 41 t:SB_CARRY
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D
 | 
				
			||||||
							
								
								
									
										23
									
								
								tests/ice40/dpram.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/ice40/dpram.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 72].
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					module top (din, write_en, waddr, wclk, raddr, rclk, dout);
 | 
				
			||||||
 | 
					parameter addr_width = 8;
 | 
				
			||||||
 | 
					parameter data_width = 8;
 | 
				
			||||||
 | 
					input [addr_width-1:0] waddr, raddr;
 | 
				
			||||||
 | 
					input [data_width-1:0] din;
 | 
				
			||||||
 | 
					input write_en, wclk, rclk;
 | 
				
			||||||
 | 
					output [data_width-1:0] dout;
 | 
				
			||||||
 | 
					reg [data_width-1:0] dout;
 | 
				
			||||||
 | 
					reg [data_width-1:0] mem [(1<<addr_width)-1:0]
 | 
				
			||||||
 | 
					/* synthesis syn_ramstyle = "no_rw_check" */ ;
 | 
				
			||||||
 | 
					always @(posedge wclk) // Write memory.
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					if (write_en)
 | 
				
			||||||
 | 
					mem[waddr] <= din; // Using write address bus.
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					always @(posedge rclk) // Read memory.
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					dout <= mem[raddr]; // Using read address bus.
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										15
									
								
								tests/ice40/dpram.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/ice40/dpram.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					read_verilog dpram.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					memory -nomap
 | 
				
			||||||
 | 
					equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40
 | 
				
			||||||
 | 
					memory
 | 
				
			||||||
 | 
					opt -full
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
				
			||||||
 | 
					sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -load postopt
 | 
				
			||||||
 | 
					cd top
 | 
				
			||||||
 | 
					select -assert-count 1 t:SB_RAM40_4K
 | 
				
			||||||
 | 
					select -assert-none t:SB_RAM40_4K %% t:* %D
 | 
				
			||||||
							
								
								
									
										73
									
								
								tests/ice40/fsm.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								tests/ice40/fsm.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,73 @@
 | 
				
			||||||
 | 
					 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,GNT0 = 3'b010,GNT1 = 3'b100,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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 module top (
 | 
				
			||||||
 | 
					input clk,
 | 
				
			||||||
 | 
					input rst,
 | 
				
			||||||
 | 
					input a,
 | 
				
			||||||
 | 
					input b,
 | 
				
			||||||
 | 
					output g0,
 | 
				
			||||||
 | 
					output g1
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fsm u_fsm ( .clock(clk),
 | 
				
			||||||
 | 
					            .reset(rst),
 | 
				
			||||||
 | 
					            .req_0(a),
 | 
				
			||||||
 | 
					            .req_1(b),
 | 
				
			||||||
 | 
					            .gnt_0(g0),
 | 
				
			||||||
 | 
					            .gnt_1(g1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										13
									
								
								tests/ice40/fsm.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/ice40/fsm.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					read_verilog fsm.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 2 t:SB_DFFESR
 | 
				
			||||||
 | 
					select -assert-count 2 t:SB_DFFSR
 | 
				
			||||||
 | 
					select -assert-count 1 t:SB_DFFSS
 | 
				
			||||||
 | 
					select -assert-count 13 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_DFFESR t:SB_DFFSR t:SB_DFFSS t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										26
									
								
								tests/ice40/ice40_opt.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/ice40/ice40_opt.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					read_verilog -icells -formal <<EOT
 | 
				
			||||||
 | 
					module top(input CI, I0, output [1:0] CO, output O);
 | 
				
			||||||
 | 
					    wire A = 1'b0, B = 1'b0;
 | 
				
			||||||
 | 
						\$__ICE40_CARRY_WRAPPER #(
 | 
				
			||||||
 | 
							//    A[0]: 1010 1010 1010 1010
 | 
				
			||||||
 | 
							//    A[1]: 1100 1100 1100 1100
 | 
				
			||||||
 | 
							//    A[2]: 1111 0000 1111 0000
 | 
				
			||||||
 | 
							//    A[3]: 1111 1111 0000 0000
 | 
				
			||||||
 | 
							.LUT(~16'b 0110_1001_1001_0110)
 | 
				
			||||||
 | 
						) u0 (
 | 
				
			||||||
 | 
							.A(A),
 | 
				
			||||||
 | 
							.B(B),
 | 
				
			||||||
 | 
							.CI(CI),
 | 
				
			||||||
 | 
							.I0(I0),
 | 
				
			||||||
 | 
							.I3(CI),
 | 
				
			||||||
 | 
							.CO(CO[0]),
 | 
				
			||||||
 | 
							.O(O)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					    SB_CARRY u1 (.I0(~A), .I1(~B), .CI(CI), .CO(CO[1]));
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt
 | 
				
			||||||
 | 
					design -load postopt
 | 
				
			||||||
 | 
					select -assert-count 1 t:*
 | 
				
			||||||
 | 
					select -assert-count 1 t:$lut
 | 
				
			||||||
							
								
								
									
										58
									
								
								tests/ice40/latches.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								tests/ice40/latches.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
					input clk,
 | 
				
			||||||
 | 
					input clr,
 | 
				
			||||||
 | 
					input pre,
 | 
				
			||||||
 | 
					input a,
 | 
				
			||||||
 | 
					output b,b1,b2
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latchp u_latchp (
 | 
				
			||||||
 | 
					        .en (clk ),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latchn u_latchn (
 | 
				
			||||||
 | 
					        .en (clk ),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b1 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latchsr u_latchsr (
 | 
				
			||||||
 | 
					        .en (clk ),
 | 
				
			||||||
 | 
					        .clr (clr),
 | 
				
			||||||
 | 
					        .pre (pre),
 | 
				
			||||||
 | 
					        .d (a ),
 | 
				
			||||||
 | 
					        .q (b2 )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										15
									
								
								tests/ice40/latches.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/ice40/latches.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					read_verilog latches.v
 | 
				
			||||||
 | 
					design -save read
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					async2sync # converts latches to a 'sync' variant clocked by a 'super'-clock
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					synth_ice40
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check
 | 
				
			||||||
 | 
					design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -load read
 | 
				
			||||||
 | 
					synth_ice40
 | 
				
			||||||
 | 
					cd top
 | 
				
			||||||
 | 
					select -assert-count 4 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										18
									
								
								tests/ice40/logic.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/ice40/logic.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										7
									
								
								tests/ice40/logic.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tests/ice40/logic.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					read_verilog logic.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										25
									
								
								tests/ice40/macc.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/ice40/macc.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 77].
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					module top(clk,a,b,c,set);
 | 
				
			||||||
 | 
					parameter A_WIDTH = 6 /*4*/;
 | 
				
			||||||
 | 
					parameter B_WIDTH = 6 /*3*/;
 | 
				
			||||||
 | 
					input set;
 | 
				
			||||||
 | 
					input clk;
 | 
				
			||||||
 | 
					input signed [(A_WIDTH - 1):0] a;
 | 
				
			||||||
 | 
					input signed [(B_WIDTH - 1):0] b;
 | 
				
			||||||
 | 
					output signed [(A_WIDTH + B_WIDTH - 1):0] c;
 | 
				
			||||||
 | 
					reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c;
 | 
				
			||||||
 | 
					assign c = reg_tmp_c;
 | 
				
			||||||
 | 
					always @(posedge clk)
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					if(set)
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					reg_tmp_c <= 0;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					reg_tmp_c <= a * b + c;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										13
									
								
								tests/ice40/macc.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/ice40/macc.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					read_verilog macc.v
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 -dsp
 | 
				
			||||||
 | 
					async2sync
 | 
				
			||||||
 | 
					equiv_opt -run prove: -assert null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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:SB_MAC16
 | 
				
			||||||
 | 
					select -assert-none t:SB_MAC16 %% t:* %D
 | 
				
			||||||
							
								
								
									
										21
									
								
								tests/ice40/memory.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/ice40/memory.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					module top
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
						input [7:0] data_a,
 | 
				
			||||||
 | 
						input [6:1] addr_a,
 | 
				
			||||||
 | 
						input we_a, clk,
 | 
				
			||||||
 | 
						output reg [7:0] q_a
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						// Declare the RAM variable
 | 
				
			||||||
 | 
						reg [7:0] ram[63:0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Port A
 | 
				
			||||||
 | 
						always @ (posedge clk)
 | 
				
			||||||
 | 
						begin
 | 
				
			||||||
 | 
							if (we_a)
 | 
				
			||||||
 | 
							begin
 | 
				
			||||||
 | 
								ram[addr_a] <= data_a;
 | 
				
			||||||
 | 
								q_a <= data_a;
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							q_a <= ram[addr_a];
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										15
									
								
								tests/ice40/memory.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/ice40/memory.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					read_verilog memory.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					memory -nomap
 | 
				
			||||||
 | 
					equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40
 | 
				
			||||||
 | 
					memory
 | 
				
			||||||
 | 
					opt -full
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
				
			||||||
 | 
					sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -load postopt
 | 
				
			||||||
 | 
					cd top
 | 
				
			||||||
 | 
					select -assert-count 1 t:SB_RAM40_4K
 | 
				
			||||||
 | 
					select -assert-none t:SB_RAM40_4K %% t:* %D
 | 
				
			||||||
							
								
								
									
										11
									
								
								tests/ice40/mul.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/ice40/mul.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					module top
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
					 input [5:0] x,
 | 
				
			||||||
 | 
					 input [5:0] y,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 output [11:0] A,
 | 
				
			||||||
 | 
					 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign A =  x * y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										7
									
								
								tests/ice40/mul.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tests/ice40/mul.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					read_verilog mul.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # 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:SB_MAC16
 | 
				
			||||||
 | 
					select -assert-none t:SB_MAC16 %% t:* %D
 | 
				
			||||||
							
								
								
									
										100
									
								
								tests/ice40/mux.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								tests/ice40/mux.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,100 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
					input [3:0] S,
 | 
				
			||||||
 | 
					input [15:0] D,
 | 
				
			||||||
 | 
					output M2,M4,M8,M16
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mux2 u_mux2 (
 | 
				
			||||||
 | 
					        .S (S[0]),
 | 
				
			||||||
 | 
					        .A (D[0]),
 | 
				
			||||||
 | 
					        .B (D[1]),
 | 
				
			||||||
 | 
					        .Y (M2)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mux4 u_mux4 (
 | 
				
			||||||
 | 
					        .S (S[1:0]),
 | 
				
			||||||
 | 
					        .D (D[3:0]),
 | 
				
			||||||
 | 
					        .Y (M4)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mux8 u_mux8 (
 | 
				
			||||||
 | 
					        .S (S[2:0]),
 | 
				
			||||||
 | 
					        .D (D[7:0]),
 | 
				
			||||||
 | 
					        .Y (M8)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mux16 u_mux16 (
 | 
				
			||||||
 | 
					        .S (S[3:0]),
 | 
				
			||||||
 | 
					        .D (D[15:0]),
 | 
				
			||||||
 | 
					        .Y (M16)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										8
									
								
								tests/ice40/mux.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/ice40/mux.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					read_verilog mux.v
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 19 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										18
									
								
								tests/ice40/rom.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/ice40/rom.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 74].
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					module top(data, addr);
 | 
				
			||||||
 | 
					output [3:0] data;
 | 
				
			||||||
 | 
					input [4:0] addr;
 | 
				
			||||||
 | 
					always @(addr) begin
 | 
				
			||||||
 | 
					case (addr)
 | 
				
			||||||
 | 
					0 : data = 'h4;
 | 
				
			||||||
 | 
					1 : data = 'h9;
 | 
				
			||||||
 | 
					2 : data = 'h1;
 | 
				
			||||||
 | 
					15 : data = 'h8;
 | 
				
			||||||
 | 
					16 : data = 'h1;
 | 
				
			||||||
 | 
					17 : data = 'h0;
 | 
				
			||||||
 | 
					default : data = 'h0;
 | 
				
			||||||
 | 
					endcase
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										8
									
								
								tests/ice40/rom.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/ice40/rom.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					read_verilog rom.v
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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 5 t:SB_LUT4
 | 
				
			||||||
 | 
					select -assert-none t:SB_LUT4 %% t:* %D
 | 
				
			||||||
							
								
								
									
										20
									
								
								tests/ice40/run-test.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								tests/ice40/run-test.sh
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					echo "all::"
 | 
				
			||||||
 | 
					for x in *.ys; do
 | 
				
			||||||
 | 
						echo "all:: run-$x"
 | 
				
			||||||
 | 
						echo "run-$x:"
 | 
				
			||||||
 | 
						echo "	@echo 'Running $x..'"
 | 
				
			||||||
 | 
						echo "	@../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					for s in *.sh; do
 | 
				
			||||||
 | 
						if [ "$s" != "run-test.sh" ]; then
 | 
				
			||||||
 | 
							echo "all:: run-$s"
 | 
				
			||||||
 | 
							echo "run-$s:"
 | 
				
			||||||
 | 
							echo "	@echo 'Running $s..'"
 | 
				
			||||||
 | 
							echo "	@bash $s"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					} > run-test.mk
 | 
				
			||||||
 | 
					exec ${MAKE:-make} -f run-test.mk
 | 
				
			||||||
							
								
								
									
										22
									
								
								tests/ice40/shifter.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/ice40/shifter.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					module top    (
 | 
				
			||||||
 | 
					out,
 | 
				
			||||||
 | 
					clk,
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					    output [7:0] out;
 | 
				
			||||||
 | 
					    input signed clk, in;
 | 
				
			||||||
 | 
					    reg signed [7:0] out = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    always @(posedge clk)
 | 
				
			||||||
 | 
						begin
 | 
				
			||||||
 | 
					`ifndef BUG
 | 
				
			||||||
 | 
							out    <= out >> 1;
 | 
				
			||||||
 | 
							out[7] <= in;
 | 
				
			||||||
 | 
					`else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							out    <= out << 1;
 | 
				
			||||||
 | 
							out[7] <= in;
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										9
									
								
								tests/ice40/shifter.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/ice40/shifter.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					read_verilog shifter.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # 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:SB_DFF
 | 
				
			||||||
 | 
					select -assert-none t:SB_DFF %% t:* %D
 | 
				
			||||||
							
								
								
									
										23
									
								
								tests/ice40/tribuf.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/ice40/tribuf.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					module tristate (en, i, o);
 | 
				
			||||||
 | 
					    input en;
 | 
				
			||||||
 | 
					    input i;
 | 
				
			||||||
 | 
					    output o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign o = en ? i : 1'bz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top (
 | 
				
			||||||
 | 
					input en,
 | 
				
			||||||
 | 
					input a,
 | 
				
			||||||
 | 
					output b
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tristate u_tri (
 | 
				
			||||||
 | 
					        .en (en ),
 | 
				
			||||||
 | 
					        .i (a ),
 | 
				
			||||||
 | 
					        .o (b )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										9
									
								
								tests/ice40/tribuf.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/ice40/tribuf.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					read_verilog tribuf.v
 | 
				
			||||||
 | 
					hierarchy -top top
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					flatten
 | 
				
			||||||
 | 
					equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 # 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:$_TBUF_
 | 
				
			||||||
 | 
					select -assert-none t:$_TBUF_ %% t:* %D
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ done
 | 
				
			||||||
shift "$((OPTIND-1))"
 | 
					shift "$((OPTIND-1))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# check for Icarus Verilog
 | 
					# check for Icarus Verilog
 | 
				
			||||||
if ! which iverilog > /dev/null ; then
 | 
					if ! command -v iverilog > /dev/null ; then
 | 
				
			||||||
  echo "$0: Error: Icarus Verilog 'iverilog' not found."
 | 
					  echo "$0: Error: Icarus Verilog 'iverilog' not found."
 | 
				
			||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ done
 | 
				
			||||||
shift "$((OPTIND-1))"
 | 
					shift "$((OPTIND-1))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# check for Icarus Verilog
 | 
					# check for Icarus Verilog
 | 
				
			||||||
if ! which iverilog > /dev/null ; then
 | 
					if ! command -v iverilog > /dev/null ; then
 | 
				
			||||||
  echo "$0: Error: Icarus Verilog 'iverilog' not found."
 | 
					  echo "$0: Error: Icarus Verilog 'iverilog' not found."
 | 
				
			||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
| 
						 | 
					@ -20,4 +20,10 @@ fi
 | 
				
			||||||
cp ../simple/*.v .
 | 
					cp ../simple/*.v .
 | 
				
			||||||
cp ../simple/*.sv .
 | 
					cp ../simple/*.sv .
 | 
				
			||||||
DOLLAR='?'
 | 
					DOLLAR='?'
 | 
				
			||||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p 'hierarchy; synth -run coarse; opt -full; techmap; abc9 -lut 4 -box ../abc.box; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
 | 
					exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p '\
 | 
				
			||||||
 | 
					    hierarchy; \
 | 
				
			||||||
 | 
					    synth -run coarse; \
 | 
				
			||||||
 | 
					    opt -full; \
 | 
				
			||||||
 | 
					    techmap; abc9 -lut 4 -box ../abc.box; \
 | 
				
			||||||
 | 
					    check -assert; \
 | 
				
			||||||
 | 
					    select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,36 +31,3 @@ sat -verify -prove-asserts -show-ports -seq 5 miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#design -load gate
 | 
					#design -load gate
 | 
				
			||||||
#stat
 | 
					#stat
 | 
				
			||||||
 | 
					 | 
				
			||||||
##########
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
design -load read
 | 
					 | 
				
			||||||
design -copy-to model $__XILINX_SHREG_
 | 
					 | 
				
			||||||
hierarchy -top shregmap_variable_test
 | 
					 | 
				
			||||||
prep
 | 
					 | 
				
			||||||
design -save gold
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
simplemap t:$dff t:$dffe
 | 
					 | 
				
			||||||
shregmap -tech xilinx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#stat
 | 
					 | 
				
			||||||
# show -width
 | 
					 | 
				
			||||||
# write_verilog -noexpr -norename
 | 
					 | 
				
			||||||
select -assert-count 1 t:$_DFF_P_
 | 
					 | 
				
			||||||
select -assert-count 2 t:$__XILINX_SHREG_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
design -stash gate
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
design -import gold -as gold
 | 
					 | 
				
			||||||
design -import gate -as gate
 | 
					 | 
				
			||||||
design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_
 | 
					 | 
				
			||||||
prep
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
					 | 
				
			||||||
sat -verify -prove-asserts -show-ports -seq 5 miter
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# design -load gold
 | 
					 | 
				
			||||||
# stat
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# design -load gate
 | 
					 | 
				
			||||||
# stat
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								tests/xilinx/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/xilinx/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					/*.log
 | 
				
			||||||
 | 
					/*.out
 | 
				
			||||||
 | 
					/run-test.mk
 | 
				
			||||||
							
								
								
									
										57
									
								
								tests/xilinx/pmgen_xilinx_srl.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								tests/xilinx/pmgen_xilinx_srl.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					read_verilog -icells <<EOT
 | 
				
			||||||
 | 
					module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO);
 | 
				
			||||||
 | 
					  parameter DEPTH = 1;
 | 
				
			||||||
 | 
					  parameter [DEPTH-1:0] INIT = 0;
 | 
				
			||||||
 | 
					  parameter CLKPOL = 1;
 | 
				
			||||||
 | 
					  parameter ENPOL = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wire pos_clk = C == CLKPOL;
 | 
				
			||||||
 | 
					  reg pos_en;
 | 
				
			||||||
 | 
					  always @(E)
 | 
				
			||||||
 | 
					    if (ENPOL == 2) pos_en = 1'b1;
 | 
				
			||||||
 | 
					    else pos_en = (E == ENPOL[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  reg [DEPTH-1:0] r;
 | 
				
			||||||
 | 
					  always @(posedge pos_clk)
 | 
				
			||||||
 | 
					    if (pos_en)
 | 
				
			||||||
 | 
					      r <= {r[DEPTH-2:0], D};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  assign Q = r[L];
 | 
				
			||||||
 | 
					  assign SO = r[DEPTH-1];
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					read_verilog +/xilinx/cells_sim.v
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					design -save model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_pmgen -generate xilinx_srl.fixed
 | 
				
			||||||
 | 
					hierarchy -top pmtest_xilinx_srl_pm_fixed
 | 
				
			||||||
 | 
					flatten; opt_clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -save gold
 | 
				
			||||||
 | 
					xilinx_srl -fixed
 | 
				
			||||||
 | 
					techmap -autoproc -map %model
 | 
				
			||||||
 | 
					design -stash gate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -copy-from gold -as gold pmtest_xilinx_srl_pm_fixed
 | 
				
			||||||
 | 
					design -copy-from gate -as gate pmtest_xilinx_srl_pm_fixed
 | 
				
			||||||
 | 
					dff2dffe -unmap # sat does not support flops-with-enable yet
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert gold gate miter
 | 
				
			||||||
 | 
					sat -set-init-zero -seq 5 -verify -prove-asserts miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -load model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_pmgen -generate xilinx_srl.variable
 | 
				
			||||||
 | 
					hierarchy -top pmtest_xilinx_srl_pm_variable
 | 
				
			||||||
 | 
					flatten; opt_clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -save gold
 | 
				
			||||||
 | 
					xilinx_srl -variable
 | 
				
			||||||
 | 
					techmap -autoproc -map %model
 | 
				
			||||||
 | 
					design -stash gate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -copy-from gold -as gold pmtest_xilinx_srl_pm_variable
 | 
				
			||||||
 | 
					design -copy-from gate -as gate pmtest_xilinx_srl_pm_variable
 | 
				
			||||||
 | 
					dff2dffe -unmap # sat does not support flops-with-enable yet
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert gold gate miter
 | 
				
			||||||
 | 
					sat -set-init-zero -seq 5 -verify -prove-asserts miter
 | 
				
			||||||
							
								
								
									
										20
									
								
								tests/xilinx/run-test.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								tests/xilinx/run-test.sh
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					echo "all::"
 | 
				
			||||||
 | 
					for x in *.ys; do
 | 
				
			||||||
 | 
						echo "all:: run-$x"
 | 
				
			||||||
 | 
						echo "run-$x:"
 | 
				
			||||||
 | 
						echo "	@echo 'Running $x..'"
 | 
				
			||||||
 | 
						echo "	@../../yosys -ql ${x%.ys}.log $x"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					for s in *.sh; do
 | 
				
			||||||
 | 
						if [ "$s" != "run-test.sh" ]; then
 | 
				
			||||||
 | 
							echo "all:: run-$s"
 | 
				
			||||||
 | 
							echo "run-$s:"
 | 
				
			||||||
 | 
							echo "	@echo 'Running $s..'"
 | 
				
			||||||
 | 
							echo "	@bash $s"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					} > run-test.mk
 | 
				
			||||||
 | 
					exec ${MAKE:-make} -f run-test.mk
 | 
				
			||||||
							
								
								
									
										40
									
								
								tests/xilinx/xilinx_srl.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tests/xilinx/xilinx_srl.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					module xilinx_srl_static_test(input i, clk, output [1:0] q);
 | 
				
			||||||
 | 
					reg head = 1'b0;
 | 
				
			||||||
 | 
					reg [3:0] shift1 = 4'b0000;
 | 
				
			||||||
 | 
					reg [3:0] shift2 = 4'b0000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @(posedge clk) begin
 | 
				
			||||||
 | 
					    head <= i;
 | 
				
			||||||
 | 
					    shift1 <= {shift1[2:0], head};
 | 
				
			||||||
 | 
					    shift2 <= {shift2[2:0], head};
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign q = {shift2[3], shift1[3]};
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module xilinx_srl_variable_test(input i, clk, input [1:0] l1, l2, output [1:0] q);
 | 
				
			||||||
 | 
					reg head = 1'b0;
 | 
				
			||||||
 | 
					reg [3:0] shift1 = 4'b0000;
 | 
				
			||||||
 | 
					reg [3:0] shift2 = 4'b0000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @(posedge clk) begin
 | 
				
			||||||
 | 
					    head <= i;
 | 
				
			||||||
 | 
					    shift1 <= {shift1[2:0], head};
 | 
				
			||||||
 | 
					    shift2 <= {shift2[2:0], head};
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign q = {shift2[l2], shift1[l1]};
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module $__XILINX_SHREG_(input C, D, E, input [1:0] L, output Q);
 | 
				
			||||||
 | 
					parameter CLKPOL = 1;
 | 
				
			||||||
 | 
					parameter ENPOL = 1;
 | 
				
			||||||
 | 
					parameter DEPTH = 1;
 | 
				
			||||||
 | 
					parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}};
 | 
				
			||||||
 | 
					reg [DEPTH-1:0] r = INIT;
 | 
				
			||||||
 | 
					wire clk = C ^ CLKPOL;
 | 
				
			||||||
 | 
					always @(posedge C)
 | 
				
			||||||
 | 
					    if (E) 
 | 
				
			||||||
 | 
					        r <= { r[DEPTH-2:0], D };
 | 
				
			||||||
 | 
					assign Q = r[L];
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										67
									
								
								tests/xilinx/xilinx_srl.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								tests/xilinx/xilinx_srl.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					read_verilog xilinx_srl.v
 | 
				
			||||||
 | 
					design -save read
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -copy-to model $__XILINX_SHREG_
 | 
				
			||||||
 | 
					hierarchy -top xilinx_srl_static_test
 | 
				
			||||||
 | 
					prep
 | 
				
			||||||
 | 
					design -save gold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					techmap
 | 
				
			||||||
 | 
					xilinx_srl -fixed
 | 
				
			||||||
 | 
					opt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# stat
 | 
				
			||||||
 | 
					# show -width
 | 
				
			||||||
 | 
					select -assert-count 1 t:$_DFF_P_
 | 
				
			||||||
 | 
					select -assert-count 2 t:$__XILINX_SHREG_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -stash gate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -import gold -as gold
 | 
				
			||||||
 | 
					design -import gate -as gate
 | 
				
			||||||
 | 
					design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_
 | 
				
			||||||
 | 
					prep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
				
			||||||
 | 
					dump gate
 | 
				
			||||||
 | 
					sat -verify -prove-asserts -show-ports -seq 5 miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#design -load gold
 | 
				
			||||||
 | 
					#stat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#design -load gate
 | 
				
			||||||
 | 
					#stat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##########
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -load read
 | 
				
			||||||
 | 
					design -copy-to model $__XILINX_SHREG_
 | 
				
			||||||
 | 
					hierarchy -top xilinx_srl_variable_test
 | 
				
			||||||
 | 
					prep
 | 
				
			||||||
 | 
					design -save gold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					xilinx_srl -variable
 | 
				
			||||||
 | 
					opt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#stat
 | 
				
			||||||
 | 
					# show -width
 | 
				
			||||||
 | 
					# write_verilog -noexpr -norename
 | 
				
			||||||
 | 
					select -assert-count 1 t:$dff
 | 
				
			||||||
 | 
					select -assert-count 1 t:$dff r:WIDTH=1 %i
 | 
				
			||||||
 | 
					select -assert-count 2 t:$__XILINX_SHREG_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -stash gate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -import gold -as gold
 | 
				
			||||||
 | 
					design -import gate -as gate
 | 
				
			||||||
 | 
					design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_
 | 
				
			||||||
 | 
					prep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
				
			||||||
 | 
					sat -verify -prove-asserts -show-ports -seq 5 miter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# design -load gold
 | 
				
			||||||
 | 
					# stat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# design -load gate
 | 
				
			||||||
 | 
					# stat
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue