diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b7a3b20 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +DIRU=/home/alex/Desktop/Hacking/libre-chip/fayalite-wip/target/blinky-out +NEXTPNR_DENSITY:=--25k + +all: + cp $(DIRU)/*.pcf /tmp + RUST_BACKTRACE=full cargo run --example blinky yosys-nextpnr-ecp5 \ + --nextpnr /home/alex/.guix-profile/bin/nextpnr-ecp5 \ + --platform orangecrab-85k -o target/blinky-out \ + --ecppack /home/alex/.guix-profile/bin/ecppack \ + --placeholder-dir /tmp/anyPathBuf/orangecrab_r0.2.1.pcf + ls -1 $(DIRU)/*.bit +ls: + ls -1 $(DIRU) +clean: + rm $(DIRU)/* +nextpnr: + cd $(DIRU) && nextpnr-ecp5 --json blinky.json --textcfg blinky.nextpnr.out $(NEXTPNR_DENSITY) \ + --package CSFBGA285 --lpf orangecrab_r0.2.1.pcf --lpf-allow-unconstrained +pack: + cd $(DIRU) && ecppack --compress --freq 38.8 --input blinky.nextpnr.out --bit blinky.nextpnr.bit + cd $(DIRU) && file *.bit \ No newline at end of file diff --git a/crates/fayalite/src/vendor.rs b/crates/fayalite/src/vendor.rs index cdf302d..e7aff58 100644 --- a/crates/fayalite/src/vendor.rs +++ b/crates/fayalite/src/vendor.rs @@ -2,11 +2,14 @@ // See Notices.txt for copyright information pub mod xilinx; +pub mod lattice; pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - xilinx::built_in_job_kinds() + xilinx::built_in_job_kinds(); + lattice::built_in_job_kinds() } pub(crate) fn built_in_platforms() -> impl IntoIterator { - xilinx::built_in_platforms() + xilinx::built_in_platforms(); + lattice::built_in_platforms() } diff --git a/crates/fayalite/src/vendor/lattice.rs b/crates/fayalite/src/vendor/lattice.rs index 1c2d5c2..a9ad5a6 100644 --- a/crates/fayalite/src/vendor/lattice.rs +++ b/crates/fayalite/src/vendor/lattice.rs @@ -12,4 +12,176 @@ use ordered_float::NotNan; use serde::{Deserialize, Serialize}; use std::fmt; -// copy of xilinx.rs with same header +pub mod orangecrab; +pub mod primitives; +pub mod yosys_nextpnr; + +#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] +pub struct LatticeArgs { + #[arg(long)] + pub device: Option, +} + +impl LatticeArgs { + pub fn require_device( + &self, + platform: Option<&DynPlatform>, + global_params: &GlobalParams, + ) -> clap::error::Result { + if let Some(device) = self.device { + return Ok(device); + } + if let Some(device) = + platform.and_then(|platform| platform.aspects().get_single_by_type::().copied()) + { + return Ok(device); + } + Err(global_params.clap_error( + clap::error::ErrorKind::MissingRequiredArgument, + "missing --device option", + )) + } +} + +impl ToArgs for LatticeArgs { + fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { + if let Some(device) = self.device { + args.write_long_option_eq("device", device.as_str()); + } + } +} + +macro_rules! make_device_enum { + ($vis:vis enum $Device:ident { + $( + #[ + name = $name:literal, + lattice_part = $lattice_part:literal, + lattice_device = $lattice_device:literal, + lattice_family = $lattice_family:literal, + ] + $variant:ident, + )* + }) => { + #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, ValueEnum)] + $vis enum $Device { + $( + #[value(name = $name, alias = $lattice_part)] + $variant, + )* + } + + impl $Device { + $vis fn as_str(self) -> &'static str { + match self { + $(Self::$variant => $name,)* + } + } + $vis fn lattice_part(self) -> &'static str { + match self { + $(Self::$variant => $lattice_part,)* + } + } + $vis fn lattice_device(self) -> &'static str { + match self { + $(Self::$variant => $lattice_device,)* + } + } + $vis fn lattice_family(self) -> &'static str { + match self { + $(Self::$variant => $lattice_family,)* + } + } + } + + struct DeviceVisitor; + + impl<'de> serde::de::Visitor<'de> for DeviceVisitor { + type Value = $Device; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a Lattice device string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + match $Device::from_str(v, false) { + Ok(v) => Ok(v), + Err(_) => Err(E::invalid_value(serde::de::Unexpected::Str(v), &self)), + } + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + match str::from_utf8(v).ok().and_then(|v| $Device::from_str(v, false).ok()) { + Some(v) => Ok(v), + None => Err(E::invalid_value(serde::de::Unexpected::Bytes(v), &self)), + } + } + } + + impl<'de> Deserialize<'de> for $Device { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_string(DeviceVisitor) + } + } + + impl Serialize for $Device { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.as_str().serialize(serializer) + } + } + }; +} + +//ECP5 variants +make_device_enum! { + pub enum Device { + #[ + name = "placeholder25k", + lattice_part = "fixme", + lattice_device = "fixme", + lattice_family = "fixme", + ] + Placeholder25k, + #[ + name = "placeholder85k", + lattice_part = "fixme", + lattice_device = "fimxe", + lattice_family = "fixme", + ] + Placeholder85k, + } +} + +//rest looks good + +impl fmt::Display for Device { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +pub(crate) fn built_in_job_kinds() -> impl IntoIterator { + orangecrab::built_in_job_kinds() + .into_iter() + .chain(yosys_nextpnr::built_in_job_kinds()) +} + +pub(crate) fn built_in_platforms() -> impl IntoIterator { + orangecrab::built_in_platforms() + .into_iter() + .chain(yosys_nextpnr::built_in_platforms()) +} + +//first step yosys -p "read_verilog $<; synth_ecp5 -json $@" diff --git a/crates/fayalite/src/vendor/lattice/orangecrab.rs b/crates/fayalite/src/vendor/lattice/orangecrab.rs index 552eb4a..b35554b 100644 --- a/crates/fayalite/src/vendor/lattice/orangecrab.rs +++ b/crates/fayalite/src/vendor/lattice/orangecrab.rs @@ -10,28 +10,29 @@ use crate::{ peripherals::{ClockInput, Led, RgbLed, Uart}, }, prelude::*, - vendor::xilinx::{ - Device, XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, + vendor::lattice::{ + Device, primitives, }, }; use ordered_float::NotNan; use std::sync::OnceLock; -macro_rules! arty_a7_platform { +//keep unchanged +macro_rules! orangecrab_platform { ( - $vis:vis enum $ArtyA7Platform:ident { + $vis:vis enum $OrangeCrabPlatform:ident { $(#[name = $name:literal, device = $device:ident] $Variant:ident,)* } ) => { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[non_exhaustive] - $vis enum $ArtyA7Platform { + $vis enum $OrangeCrabPlatform { $($Variant,)* } - impl $ArtyA7Platform { + impl $OrangeCrabPlatform { $vis const VARIANTS: &'static [Self] = &[$(Self::$Variant,)*]; $vis fn device(self) -> Device { match self { @@ -55,15 +56,17 @@ macro_rules! arty_a7_platform { }; } -arty_a7_platform! { - pub enum ArtyA7Platform { - #[name = "arty-a7-35t", device = Xc7a35ticsg324_1l] - ArtyA7_35T, - #[name = "arty-a7-100t", device = Xc7a100ticsg324_1l] - ArtyA7_100T, +//untested +orangecrab_platform! { + pub enum OrangeCrabPlatform { + #[name = "orangecrab-25k", device = Placeholder25k] + OrangeCrab_25k, + #[name = "orangecrab-85k", device = Placeholder85k] + OrangeCrab_85k, } } +//FIXME #[derive(Debug)] pub struct ArtyA7Peripherals { clk100_div_pow2: [Peripheral; 4], @@ -112,7 +115,7 @@ impl Peripherals for ArtyA7Peripherals { } } -impl ArtyA7Platform { +impl OrangeCrabPlatform { fn make_aspects(self) -> PlatformAspectSet { let mut retval = PlatformAspectSet::new(); retval.insert_new(self.device()); @@ -129,37 +132,21 @@ fn reset_sync() { #[hdl] let out: SyncReset = m.output(); m.annotate_module(BlackBoxInlineAnnotation { - path: "fayalite_arty_a7_reset_sync.v".intern(), - text: r#"module __fayalite_arty_a7_reset_sync(input clk, input inp, output out); + path: "fayalite_orangecrab_reset_sync.v".intern(), + text: r#"module __fayalite_orangecrab_reset_sync(input clk, input inp, output out); wire reset_0_out; - (* ASYNC_REG = "TRUE" *) - FDPE #( - .INIT(1'b1) - ) reset_0 ( - .Q(reset_0_out), - .C(clk), - .CE(1'b1), - .PRE(inp), - .D(1'b0) - ); - (* ASYNC_REG = "TRUE" *) - FDPE #( - .INIT(1'b1) - ) reset_1 ( - .Q(out), - .C(clk), - .CE(1'b1), - .PRE(inp), - .D(reset_0_out) - ); + always @(posedge clk) begin + reset_0_out <= inp; + outp <= reset_0_out; + end endmodule "# .intern(), }); - m.verilog_name("__fayalite_arty_a7_reset_sync"); + m.verilog_name("__fayalite_orangecrab_reset_sync"); } -impl Platform for ArtyA7Platform { +impl Platform for OrangeCrabPlatform { type Peripherals = ArtyA7Peripherals; fn name(&self) -> Interned { @@ -222,29 +209,30 @@ impl Platform for ArtyA7Platform { } = peripherals; let make_buffered_input = |name: &str, location: &str, io_standard: &str, invert: bool| { let pin = m.input_with_loc(name, SourceLocation::builtin(), Bool); - annotate( + /* fixme annotate( pin, XdcLocationAnnotation { location: location.intern(), }, - ); - annotate( + ); */ + /* fixme annotate( pin, XdcIOStandardAnnotation { value: io_standard.intern(), }, - ); - let buf = instance_with_loc( - &format!("{name}_buf"), - primitives::IBUF(), - SourceLocation::builtin(), - ); - connect(buf.I, pin); - if invert { !buf.O } else { buf.O } + ); */ + //let buf = instance_with_loc( + // &format!("{name}_buf"), + // //primitives::IBUF(), + // SourceLocation::builtin(), + //); + //connect(buf.I, pin); + //if invert { !buf.O } else { buf.O } + if invert { !pin } else { pin } }; let make_buffered_output = |name: &str, location: &str, io_standard: &str| { let pin = m.output_with_loc(name, SourceLocation::builtin(), Bool); - annotate( + /* fixme annotate( pin, XdcLocationAnnotation { location: location.intern(), @@ -255,15 +243,16 @@ impl Platform for ArtyA7Platform { XdcIOStandardAnnotation { value: io_standard.intern(), }, - ); - let buf = instance_with_loc( - &format!("{name}_buf"), - primitives::OBUFT(), - SourceLocation::builtin(), - ); - connect(pin, buf.O); - connect(buf.T, false); - buf.I + ); */ + //let buf = instance_with_loc( + // &format!("{name}_buf"), + // primitives::OBUFT(), + // SourceLocation::builtin(), + //); + //connect(pin, buf.O); + //connect(buf.T, false); + //buf.I + pin }; let mut frequency = clk100_div_pow2[0].ty().frequency(); let mut log2_divisor = 0; @@ -281,17 +270,17 @@ impl Platform for ArtyA7Platform { log2_divisor = cur_log2_divisor; } let clk100_buf = make_buffered_input("clk100", "E3", "LVCMOS33", false); - let startup = instance_with_loc( - "startup", - primitives::STARTUPE2_default_inputs(), - SourceLocation::builtin(), - ); - let clk_global_buf = instance_with_loc( - "clk_global_buf", - primitives::BUFGCE(), - SourceLocation::builtin(), - ); - connect(clk_global_buf.CE, startup.EOS); + //let startup = instance_with_loc( + // "startup", + // primitives::STARTUPE2_default_inputs(), + // SourceLocation::builtin(), + //); + //let clk_global_buf = instance_with_loc( + // "clk_global_buf", + // primitives::BUFGCE(), + // SourceLocation::builtin(), + //); + //connect(clk_global_buf.CE, startup.EOS); let mut clk_global_buf_in = clk100_buf.to_clock(); for prev_log2_divisor in 0..log2_divisor { let prev_divisor = 1u64 << prev_log2_divisor; @@ -301,13 +290,14 @@ impl Platform for ArtyA7Platform { Clock, ); connect(clk_in, clk_global_buf_in); + /* fixme annotate( clk_in, XdcCreateClockAnnotation { period: NotNan::new(1e9 / (100e6 / prev_divisor as f64)) .expect("known to be valid"), }, - ); + ); */ annotate(clk_in, DontTouchAnnotation); let cd = wire_with_loc( &format!("clk_div_{prev_divisor}_in"), @@ -315,7 +305,7 @@ impl Platform for ArtyA7Platform { ClockDomain[AsyncReset], ); connect(cd.clk, clk_in); - connect(cd.rst, (!startup.EOS).to_async_reset()); + //FIXME connect(cd.rst, (!startup.EOS).to_async_reset()); let divider = reg_builder_with_loc("divider", SourceLocation::builtin()) .clock_domain(cd) .reset(false) @@ -323,24 +313,26 @@ impl Platform for ArtyA7Platform { connect(divider, !divider); clk_global_buf_in = divider.to_clock(); } - connect(clk_global_buf.I, clk_global_buf_in); + //connect(clk_global_buf.I, clk_global_buf_in); let clk_out = wire_with_loc("clk_out", SourceLocation::builtin(), Clock); - connect(clk_out, clk_global_buf.O); - annotate( + //connect(clk_out, clk_global_buf.O); + connect(clk_out, clk_global_buf_in); + /* fixme annotate( clk_out, XdcCreateClockAnnotation { period: NotNan::new(1e9 / frequency).expect("known to be valid"), }, - ); + ); */ annotate(clk_out, DontTouchAnnotation); if let Some(clk) = clk { connect(clk.instance_io_field().clk, clk_out); } + //undo 1 let rst_value = { let rst_buf = make_buffered_input("rst", "C2", "LVCMOS33", true); let rst_sync = instance_with_loc("rst_sync", reset_sync(), SourceLocation::builtin()); connect(rst_sync.clk, clk_out); - connect(rst_sync.inp, rst_buf | !startup.EOS); + connect(rst_sync.inp, rst_buf/* | !startup.EOS*/); //FIXME rst_sync.out }; if let Some(rst) = rst.into_used() { @@ -398,7 +390,7 @@ pub(crate) fn built_in_job_kinds() -> impl IntoIterator impl IntoIterator { - ArtyA7Platform::VARIANTS + OrangeCrabPlatform::VARIANTS .iter() .map(|&v| DynPlatform::new(v)) } diff --git a/crates/fayalite/src/vendor/lattice/primitives.rs b/crates/fayalite/src/vendor/lattice/primitives.rs index 018eab3..f5f07bb 100644 --- a/crates/fayalite/src/vendor/lattice/primitives.rs +++ b/crates/fayalite/src/vendor/lattice/primitives.rs @@ -6,5 +6,45 @@ use crate::prelude::*; //#[hdl_module(extern)] -//pub fn PLACEHOLDER() { -//do this first +//pub fn IBUF() { +// m.verilog_name("IBUF"); +// #[hdl] +// let O: Bool = m.output(); +// #[hdl] +// let I: Bool = m.input(); +//} + +//#[hdl_module(extern)] +//pub fn OBUFT() { +// m.verilog_name("OBUFT"); +// #[hdl] +// let O: Bool = m.output(); +// #[hdl] +// let I: Bool = m.input(); +// #[hdl] +// let T: Bool = m.input(); +//} + +//#[hdl_module(extern)] +//pub fn BUFGCE() { +// m.verilog_name("BUFGCE"); +// #[hdl] +// let O: Clock = m.output(); +// #[hdl] +// let CE: Bool = m.input(); +// #[hdl] +// let I: Clock = m.input(); +//} + +#[hdl_module(extern)] +pub fn FIXME_PLACEHOLDER() { + m.verilog_name("FIXME_PLACEHOLDER"); + #[hdl] + let CFGCLK: Clock = m.output(); + #[hdl] + let CFGMCLK: Clock = m.output(); + #[hdl] + let EOS: Bool = m.output(); + #[hdl] + let PREQ: Bool = m.output(); +} diff --git a/crates/fayalite/src/vendor/lattice/yosys_nextpnr_trellis.rs b/crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs similarity index 59% rename from crates/fayalite/src/vendor/lattice/yosys_nextpnr_trellis.rs rename to crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs index 94ab863..6164609 100644 --- a/crates/fayalite/src/vendor/lattice/yosys_nextpnr_trellis.rs +++ b/crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs @@ -24,8 +24,8 @@ use crate::{ source_location::SourceLocation, util::{HashSet, job_server::AcquiredJob}, vendor::lattice::{ - Device, XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, - LatticeAnnotation, LatticeArgs, + Device, + /* fixme LatticeAnnotation,*/ LatticeArgs, }, }; use eyre::Context; @@ -39,26 +39,26 @@ use std::{ }; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] -pub struct YosysNextpnrTrellisWriteYsFileJobKind; +pub struct YosysNextpnrWriteYsFileJobKind; #[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrTrellisWriteYsFileArgs {} +pub struct YosysNextpnrWriteYsFileArgs {} -impl ToArgs for YosysNextpnrTrellisWriteYsFileArgs { +impl ToArgs for YosysNextpnrWriteYsFileArgs { fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { let Self {} = self; } } #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrTrellisWriteYsFile { +pub struct YosysNextpnrWriteYsFile { main_verilog_file: Interned, ys_file: Interned, json_file: Interned, json_file_name: Interned, } -impl YosysNextpnrTrellisWriteYsFile { +impl YosysNextpnrWriteYsFile { pub fn main_verilog_file(&self) -> Interned { self.main_verilog_file } @@ -91,7 +91,7 @@ impl YosysNextpnrTrellisWriteYsFile { let circuit_name = crate::firrtl::get_circuit_name(main_module_name_id); writeln!( output, - "synth_lattice -flatten -abc9 -nobram -arch xc7 -top {circuit_name}" + "synth_ecp5 -top {circuit_name}" ) .expect("writing to OsString can't fail"); output.push("write_json \""); @@ -101,9 +101,9 @@ impl YosysNextpnrTrellisWriteYsFile { } } -impl JobKind for YosysNextpnrTrellisWriteYsFileJobKind { - type Args = YosysNextpnrTrellisWriteYsFileArgs; - type Job = YosysNextpnrTrellisWriteYsFile; +impl JobKind for YosysNextpnrWriteYsFileJobKind { + type Args = YosysNextpnrWriteYsFileArgs; + type Job = YosysNextpnrWriteYsFile; type Dependencies = JobKindAndDependencies; fn dependencies(self) -> Self::Dependencies { @@ -123,11 +123,11 @@ impl JobKind for YosysNextpnrTrellisWriteYsFileJobKind { .verilog_dialect .get_or_insert(VerilogDialect::Yosys); args.args_to_jobs_simple(params, global_params, |_kind, args, dependencies| { - let YosysNextpnrTrellisWriteYsFileArgs {} = args; + let YosysNextpnrWriteYsFileArgs {} = args; let base_job = dependencies.get_job::(); let verilog_job = dependencies.get_job::(); let json_file = base_job.file_with_ext("json"); - Ok(YosysNextpnrTrellisWriteYsFile { + Ok(YosysNextpnrWriteYsFile { main_verilog_file: verilog_job.main_verilog_file(), ys_file: base_job.file_with_ext("ys"), json_file, @@ -150,7 +150,7 @@ impl JobKind for YosysNextpnrTrellisWriteYsFileJobKind { } fn name(self) -> Interned { - "yosys-nextpnr-trellis-write-ys-file".intern() + "yosys-nextpnr-ecp5-write-ys-file".intern() } fn external_command_params(self, _job: &Self::Job) -> Option { @@ -188,26 +188,26 @@ impl JobKind for YosysNextpnrTrellisWriteYsFileJobKind { } #[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrTrellisSynthArgs {} +pub struct YosysNextpnrSynthArgs {} -impl ToArgs for YosysNextpnrTrellisSynthArgs { +impl ToArgs for YosysNextpnrSynthArgs { fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { let Self {} = self; } } #[derive(Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -pub struct YosysNextpnrTrellisSynth { +pub struct YosysNextpnrSynth { #[serde(flatten)] - write_ys_file: YosysNextpnrTrellisWriteYsFile, + write_ys_file: YosysNextpnrWriteYsFile, ys_file_name: Interned, } -impl fmt::Debug for YosysNextpnrTrellisSynth { +impl fmt::Debug for YosysNextpnrSynth { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { write_ys_file: - YosysNextpnrTrellisWriteYsFile { + YosysNextpnrWriteYsFile { main_verilog_file, ys_file, json_file, @@ -215,7 +215,7 @@ impl fmt::Debug for YosysNextpnrTrellisSynth { }, ys_file_name, } = self; - f.debug_struct("YosysNextpnrTrellisSynth") + f.debug_struct("YosysNextpnrSynth") .field("main_verilog_file", main_verilog_file) .field("ys_file", ys_file) .field("ys_file_name", ys_file_name) @@ -225,7 +225,7 @@ impl fmt::Debug for YosysNextpnrTrellisSynth { } } -impl YosysNextpnrTrellisSynth { +impl YosysNextpnrSynth { pub fn main_verilog_file(&self) -> Interned { self.write_ys_file.main_verilog_file() } @@ -248,19 +248,19 @@ pub struct Yosys; impl ExternalProgramTrait for Yosys { fn default_program_name() -> Interned { - "yosys".intern() + "yosys".intern() //must be yosys } } -impl ExternalCommand for YosysNextpnrTrellisSynth { - type AdditionalArgs = YosysNextpnrTrellisSynthArgs; +impl ExternalCommand for YosysNextpnrSynth { + type AdditionalArgs = YosysNextpnrSynthArgs; type AdditionalJobData = Self; type BaseJobPosition = GetJobPositionDependencies< GetJobPositionDependencies< GetJobPositionDependencies<::BaseJobPosition>, >, >; - type Dependencies = JobKindAndDependencies; + type Dependencies = JobKindAndDependencies; type ExternalProgram = Yosys; fn dependencies() -> Self::Dependencies { @@ -276,7 +276,7 @@ impl ExternalCommand for YosysNextpnrTrellisSynth { ::JobsAndKinds, )> { args.args_to_jobs_external_simple(params, global_params, |args, dependencies| { - let YosysNextpnrTrellisSynthArgs {} = args.additional_args; + let YosysNextpnrSynthArgs {} = args.additional_args; Ok(Self { write_ys_file: dependencies.job.job.clone(), ys_file_name: dependencies @@ -318,7 +318,7 @@ impl ExternalCommand for YosysNextpnrTrellisSynth { } fn job_kind_name() -> Interned { - "yosys-nextpnr-trellis-synth".intern() + "yosys-nextpnr-ecp5-synth".intern() } fn subcommand_hidden() -> bool { @@ -327,33 +327,33 @@ impl ExternalCommand for YosysNextpnrTrellisSynth { } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] -pub struct YosysNextpnrTrellisWriteXdcFileJobKind; +pub struct YosysNextpnrWritePcfFileJobKind; #[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrTrellisWriteXdcFileArgs {} +pub struct YosysNextpnrWritePcfFileArgs {} -impl ToArgs for YosysNextpnrTrellisWriteXdcFileArgs { +impl ToArgs for YosysNextpnrWritePcfFileArgs { fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { let Self {} = self; } } #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrTrellisWriteXdcFile { +pub struct YosysNextpnrWritePcfFile { firrtl_export_options: crate::firrtl::ExportOptions, output_dir: Interned, - xdc_file: Interned, + pcf_file: Interned, } -struct WriteXdcContentsError(eyre::Report); +struct WritePcfContentsError(eyre::Report); -impl From for WriteXdcContentsError { +impl From for WritePcfContentsError { fn from(v: eyre::Report) -> Self { Self(v) } } -impl From for WriteXdcContentsError { +impl From for WritePcfContentsError { fn from(_v: fmt::Error) -> Self { unreachable!("String write can't fail") } @@ -395,7 +395,7 @@ impl AnnotationTarget { } } -struct XdcFileWriter { +struct PcfFileWriter { //TODO output: W, module_depth: usize, annotation_target: AnnotationTarget, @@ -403,8 +403,8 @@ struct XdcFileWriter { required_dont_touch_targets: HashSet>, } -impl XdcFileWriter { - fn run(output: W, top_module: Module) -> Result<(), WriteXdcContentsError> { +impl PcfFileWriter { + fn run(output: W, top_module: Module) -> Result<(), WritePcfContentsError> { let mut this = Self { output, module_depth: 0, @@ -433,7 +433,7 @@ impl XdcFileWriter { module_depth: usize, annotation_target: AnnotationTarget, v: &T, - ) -> Result<(), WriteXdcContentsError> { + ) -> Result<(), WritePcfContentsError> { let Self { output: _, module_depth: old_module_depth, @@ -450,8 +450,8 @@ impl XdcFileWriter { } } -impl Visitor for XdcFileWriter { - type Error = WriteXdcContentsError; +impl Visitor for PcfFileWriter { + type Error = WritePcfContentsError; fn visit_targeted_annotation(&mut self, v: &TargetedAnnotation) -> Result<(), Self::Error> { self.default_visit_with(self.module_depth, AnnotationTarget::Target(v.target()), v) @@ -486,161 +486,21 @@ impl Visitor for XdcFileWriter { Ok(()) } - fn visit_lattice_annotation(&mut self, v: &LatticeAnnotation) -> Result<(), Self::Error> { - fn todo( - msg: &str, - annotation: &LatticeAnnotation, - source_location: SourceLocation, - ) -> Result { - Err(WriteXdcContentsError(eyre::eyre!( - "{msg}\nannotation: {annotation:?}\nat: {source_location}" - ))) - } - if self.module_depth != 1 { - match todo( - "annotations are not yet supported outside of the top module since the logic to figure out the correct name isn't implemented", - v, - self.annotation_target.source_location(), - )? {} - } - match self.annotation_target { - AnnotationTarget::None => unreachable!(), - AnnotationTarget::Module(module) => match v { - LatticeAnnotation::XdcIOStandard(_) - | LatticeAnnotation::XdcLocation(_) - | LatticeAnnotation::XdcCreateClock(_) => { - return Err(WriteXdcContentsError(eyre::eyre!( - "annotation not allowed on a module: {v:?}\nat: {}", - module.source_location(), - ))); - } - }, - AnnotationTarget::Mem(mem) => match todo( - "lattice annotations are not yet supported on memories since the logic to figure out the correct name isn't implemented", - v, - mem.source_location(), - )? {}, - AnnotationTarget::Target(target) => { - let base = target.base(); - match *base { - TargetBase::ModuleIO(_) => { - // already handled by write_xdc_contents handling the main module's ScalarizedModuleABI - Ok(()) - } - TargetBase::MemPort(mem_port) => { - match todo( - "lattice annotations are not yet supported on memory ports since the logic to figure out the correct name isn't implemented", - v, - mem_port.source_location(), - )? {} - } - TargetBase::Reg(_) - | TargetBase::RegSync(_) - | TargetBase::RegAsync(_) - | TargetBase::Wire(_) => { - match *target { - Target::Base(_) => {} - Target::Child(_) => match todo( - "lattice annotations are not yet supported on parts of registers/wires since the logic to figure out the correct name isn't implemented", - v, - base.source_location(), - )? {}, - } - match base.canonical_ty() { - CanonicalType::UInt(_) - | CanonicalType::SInt(_) - | CanonicalType::Bool(_) - | CanonicalType::AsyncReset(_) - | CanonicalType::SyncReset(_) - | CanonicalType::Reset(_) - | CanonicalType::Clock(_) => {} - CanonicalType::Enum(_) - | CanonicalType::Array(_) - | CanonicalType::Bundle(_) - | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => match todo( - "lattice annotations are not yet supported on types other than integers, Bool, resets, or Clock since the logic to figure out the correct name isn't implemented", - v, - base.source_location(), - )? {}, - } - self.required_dont_touch_targets.insert(target); - match v { - LatticeAnnotation::XdcIOStandard(_) - | LatticeAnnotation::XdcLocation(_) => { - return Err(WriteXdcContentsError(eyre::eyre!( - "annotation must be on a ModuleIO: {v:?}\nat: {}", - base.source_location(), - ))); - } - LatticeAnnotation::XdcCreateClock(XdcCreateClockAnnotation { - period, - }) => { - let TargetName(ScopedNameId(_, NameId(name, _)), _) = - base.target_name(); - writeln!( - self.output, - "create_clock -period {period} [get_nets {}]", - tcl_escape(name), - )?; - Ok(()) - } - } - } - TargetBase::Instance(instance) => match todo( - "lattice annotations are not yet supported on instances' IO since the logic to figure out the correct name isn't implemented", - v, - instance.source_location(), - )? {}, - } - } - } - } + + /* FIXME fn visit_lattice_annotation(&mut self, v: &LatticeAnnotation) -> Result<(), Self::Error> */ } -impl YosysNextpnrTrellisWriteXdcFile { - fn write_xdc_contents_for_port_and_annotations( +impl YosysNextpnrWritePcfFile { + fn write_pcf_contents_for_port_and_annotations( &self, output: &mut impl fmt::Write, port: &ScalarizedModuleABIPort, annotations: ScalarizedModuleABIAnnotations<'_>, - ) -> Result<(), WriteXdcContentsError> { - for annotation in annotations { - match annotation.annotation() { - Annotation::DontTouch(_) - | Annotation::SVAttribute(_) - | Annotation::BlackBoxInline(_) - | Annotation::BlackBoxPath(_) - | Annotation::DocString(_) - | Annotation::CustomFirrtl(_) => {} - Annotation::Lattice(LatticeAnnotation::XdcLocation(XdcLocationAnnotation { - location, - })) => writeln!( - output, - "set_property LOC {} [get_ports {}]", - tcl_escape(location), - tcl_escape(port.scalarized_name()), - )?, - Annotation::Lattice(LatticeAnnotation::XdcIOStandard(XdcIOStandardAnnotation { - value, - })) => writeln!( - output, - "set_property IOSTANDARD {} [get_ports {}]", - tcl_escape(value), - tcl_escape(port.scalarized_name()), - )?, - Annotation::Lattice(LatticeAnnotation::XdcCreateClock( - XdcCreateClockAnnotation { period }, - )) => writeln!( - output, - "create_clock -period {period} [get_ports {}]", - tcl_escape(port.scalarized_name()), - )?, - } - } + ) -> Result<(), WritePcfContentsError> { + /* fixme for annotation in annotations .. */ Ok(()) } - fn write_xdc_contents( + fn write_pcf_contents( &self, output: &mut String, top_module: &Module, @@ -649,7 +509,7 @@ impl YosysNextpnrTrellisWriteXdcFile { ScalarizedModuleABI::new(top_module, self.firrtl_export_options) .map_err(eyre::Report::from)?; match scalarized_module_abi.for_each_port_and_annotations(|port, annotations| { - match self.write_xdc_contents_for_port_and_annotations(output, port, annotations) { + match self.write_pcf_contents_for_port_and_annotations(output, port, annotations) { Ok(()) => ControlFlow::Continue(()), Err(e) => ControlFlow::Break(e), } @@ -657,14 +517,14 @@ impl YosysNextpnrTrellisWriteXdcFile { ControlFlow::Continue(()) => {} ControlFlow::Break(e) => return Err(e.0), } - XdcFileWriter::run(output, *top_module).map_err(|e| e.0) + PcfFileWriter::run(output, *top_module).map_err(|e| e.0) } } -impl JobKind for YosysNextpnrTrellisWriteXdcFileJobKind { - type Args = YosysNextpnrTrellisWriteXdcFileArgs; - type Job = YosysNextpnrTrellisWriteXdcFile; - type Dependencies = JobKindAndDependencies>; +impl JobKind for YosysNextpnrWritePcfFileJobKind { + type Args = YosysNextpnrWritePcfFileArgs; + type Job = YosysNextpnrWritePcfFile; + type Dependencies = JobKindAndDependencies>; fn dependencies(self) -> Self::Dependencies { Default::default() @@ -685,12 +545,12 @@ impl JobKind for YosysNextpnrTrellisWriteXdcFileJobKind { .args .export_options; args.args_to_jobs_simple(params, global_params, |_kind, args, dependencies| { - let YosysNextpnrTrellisWriteXdcFileArgs {} = args; + let YosysNextpnrWritePcfFileArgs {} = args; let base_job = dependencies.get_job::(); - Ok(YosysNextpnrTrellisWriteXdcFile { + Ok(YosysNextpnrWritePcfFile { firrtl_export_options, output_dir: base_job.output_dir(), - xdc_file: base_job.file_with_ext("xdc"), + pcf_file: base_job.file_with_ext("pcf"), }) }) } @@ -703,11 +563,11 @@ impl JobKind for YosysNextpnrTrellisWriteXdcFileJobKind { } fn outputs(self, job: &Self::Job) -> Interned<[JobItemName]> { - [JobItemName::Path { path: job.xdc_file }].intern_slice() + [JobItemName::Path { path: job.pcf_file }].intern_slice() } fn name(self) -> Interned { - "yosys-nextpnr-trellis-write-xdc-file".intern() + "yosys-nextpnr-ecp5-write-pcf-file".intern() } fn external_command_params(self, _job: &Self::Job) -> Option { @@ -723,10 +583,10 @@ impl JobKind for YosysNextpnrTrellisWriteXdcFileJobKind { _acquired_job: &mut AcquiredJob, ) -> eyre::Result> { assert!(inputs.iter().map(JobItem::name).eq(self.inputs(job))); - let mut xdc = String::new(); - job.write_xdc_contents(&mut xdc, params.main_module())?; - std::fs::write(job.xdc_file, xdc)?; - Ok(vec![JobItem::Path { path: job.xdc_file }]) + let mut pcf = String::new(); + job.write_pcf_contents(&mut pcf, params.main_module())?; + std::fs::write(job.pcf_file, pcf)?; + Ok(vec![JobItem::Path { path: job.pcf_file }]) } fn subcommand_hidden(self) -> bool { @@ -739,65 +599,49 @@ pub struct NextpnrLattice; impl ExternalProgramTrait for NextpnrLattice { fn default_program_name() -> Interned { - "nextpnr-lattice".intern() + "nextpnr".intern() } } #[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrTrellisRunNextpnrArgs { +pub struct YosysNextpnrRunNextpnrArgs { #[command(flatten)] pub common: LatticeArgs, - #[arg(long, env = "CHIPDB_DIR", value_hint = clap::ValueHint::DirPath)] - pub nextpnr_lattice_chipdb_dir: PathBuf, #[arg(long, default_value_t = 0)] pub nextpnr_lattice_seed: i32, } -impl ToArgs for YosysNextpnrTrellisRunNextpnrArgs { +impl ToArgs for YosysNextpnrRunNextpnrArgs { fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { let Self { common, - nextpnr_lattice_chipdb_dir, nextpnr_lattice_seed, } = self; common.to_args(args); - args.write_long_option_eq("nextpnr-lattice-chipdb-dir", nextpnr_lattice_chipdb_dir); args.write_display_arg(format_args!("--nextpnr-lattice-seed={nextpnr_lattice_seed}")); } } #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrTrellisRunNextpnr { - nextpnr_lattice_chipdb_dir: Interned, +pub struct YosysNextpnrRunNextpnr { device: Device, nextpnr_lattice_seed: i32, - xdc_file: Interned, - xdc_file_name: Interned, + pcf_file: Interned, json_file: Interned, json_file_name: Interned, routed_json_file: Interned, routed_json_file_name: Interned, - fasm_file: Interned, - fasm_file_name: Interned, + textcfg_file: Interned, + textcfg_file_name: Interned, } -impl YosysNextpnrTrellisRunNextpnr { - fn chipdb_file(&self) -> Interned { - let mut retval = self - .nextpnr_lattice_chipdb_dir - .join(self.device.trellis_device()); - retval.set_extension("bin"); - retval.intern_deref() - } -} - -impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { - type AdditionalArgs = YosysNextpnrTrellisRunNextpnrArgs; +impl ExternalCommand for YosysNextpnrRunNextpnr { + type AdditionalArgs = YosysNextpnrRunNextpnrArgs; type AdditionalJobData = Self; type BaseJobPosition = GetJobPositionDependencies< - GetJobPositionDependencies<::BaseJobPosition>, + GetJobPositionDependencies<::BaseJobPosition>, >; - type Dependencies = JobKindAndDependencies; + type Dependencies = JobKindAndDependencies; type ExternalProgram = NextpnrLattice; fn dependencies() -> Self::Dependencies { @@ -813,35 +657,29 @@ impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { ::JobsAndKinds, )> { args.args_to_jobs_external_simple(params, global_params, |args, dependencies| { - let YosysNextpnrTrellisRunNextpnrArgs { + let YosysNextpnrRunNextpnrArgs { common, - nextpnr_lattice_chipdb_dir, nextpnr_lattice_seed, } = args.additional_args; let base_job = dependencies.get_job::(); - let write_xdc_file = dependencies.get_job::(); - let synth = dependencies.get_job::, _>(); + let write_pcf_file = dependencies.get_job::(); + let synth = dependencies.get_job::, _>(); let routed_json_file = base_job.file_with_ext("routed.json"); - let fasm_file = base_job.file_with_ext("fasm"); + let textcfg_file = base_job.file_with_ext("config"); //file must exist Ok(Self { - nextpnr_lattice_chipdb_dir: nextpnr_lattice_chipdb_dir.intern_deref(), device: common.require_device(base_job.platform(), global_params)?, nextpnr_lattice_seed, - xdc_file: write_xdc_file.xdc_file, - xdc_file_name: write_xdc_file - .xdc_file - .interned_file_name() - .expect("known to have file name"), + pcf_file: write_pcf_file.pcf_file, json_file: synth.additional_job_data().json_file(), json_file_name: synth.additional_job_data().json_file_name(), - routed_json_file, + routed_json_file: routed_json_file, routed_json_file_name: routed_json_file .interned_file_name() .expect("known to have file name"), - fasm_file, - fasm_file_name: fasm_file + textcfg_file:textcfg_file, + textcfg_file_name: textcfg_file .interned_file_name() - .expect("known to have file name"), + .expect("known to have file name"), }) }) } @@ -852,7 +690,7 @@ impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { path: job.additional_job_data().json_file, }, JobItemName::Path { - path: job.additional_job_data().xdc_file, + path: job.additional_job_data().pcf_file, }, ] .intern_slice() @@ -861,26 +699,26 @@ impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]> { [ job.additional_job_data().routed_json_file, - job.additional_job_data().fasm_file, ] .intern_slice() } fn command_line_args(job: &ExternalCommandJob, args: &mut W) { - let job_data @ YosysNextpnrTrellisRunNextpnr { + let job_data @ YosysNextpnrRunNextpnr { nextpnr_lattice_seed, - xdc_file_name, json_file_name, routed_json_file_name, - fasm_file_name, + textcfg_file_name, .. } = job.additional_job_data(); - args.write_long_option_eq("chipdb", job_data.chipdb_file()); - args.write_long_option_eq("xdc", xdc_file_name); args.write_long_option_eq("json", json_file_name); - args.write_long_option_eq("write", routed_json_file_name); - args.write_long_option_eq("fasm", fasm_file_name); - args.write_display_arg(format_args!("--seed={nextpnr_lattice_seed}")); + args.write_long_option_eq("textcfg",textcfg_file_name); + args.write_arg("--25k"); + args.write_long_option_eq("package","CSFBGA285"); + args.write_long_option_eq("lpf","/tmp/orangecrab_r0.2.1.pcf"); + args.write_arg("--lpf-allow-unconstrained"); + //???args.write_display_arg(format_args!("--seed={nextpnr_lattice_seed}")); + } fn current_dir(job: &ExternalCommandJob) -> Option> { @@ -888,7 +726,7 @@ impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { } fn job_kind_name() -> Interned { - "yosys-nextpnr-trellis-run-nextpnr".intern() + "yosys-nextpnr-ecp5-run-nextpnr".intern() } fn subcommand_hidden() -> bool { @@ -896,62 +734,75 @@ impl ExternalCommand for YosysNextpnrTrellisRunNextpnr { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] -pub struct Xcfasm; - -impl ExternalProgramTrait for Xcfasm { - fn default_program_name() -> Interned { - "xcfasm".intern() - } -} - #[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrTrellisArgs { +pub struct YosysNextpnrArgs { #[arg(long, env = "DB_DIR", value_hint = clap::ValueHint::DirPath)] - pub prjtrellis_db_dir: PathBuf, + pub pcf1: PathBuf, } -impl ToArgs for YosysNextpnrTrellisArgs { +impl ToArgs for YosysNextpnrArgs { fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { - let Self { prjtrellis_db_dir } = self; - args.write_long_option_eq("prjtrellis-db-dir", prjtrellis_db_dir); + let Self { pcf1 } = self; + args.write_long_option_eq("pcf1", pcf1); } } #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrTrellis { - prjtrellis_db_dir: Interned, +pub struct YosysNextpnr { + pcf1: Interned, device: Device, - fasm_file: Interned, - fasm_file_name: Interned, frames_file: Interned, frames_file_name: Interned, bit_file: Interned, bit_file_name: Interned, } -impl YosysNextpnrTrellis { - fn db_root(&self) -> Interned { - self.prjtrellis_db_dir - .join(self.device.trellis_family()) - .intern_deref() - } - fn part_file(&self) -> Interned { - let mut retval = self.prjtrellis_db_dir.join(self.device.trellis_family()); - retval.push(self.device.trellis_part()); - retval.push("part.yaml"); - retval.intern_deref() + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] +pub struct Ecppack; + +impl ExternalProgramTrait for Ecppack { + fn default_program_name() -> Interned { + "ecppack".intern() } } -impl ExternalCommand for YosysNextpnrTrellis { - type AdditionalArgs = YosysNextpnrTrellisArgs; +//begin +#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] +pub struct YosysNextpnrRunEcpPackArgs { + #[arg(long, env = "DB_DIR", value_hint = clap::ValueHint::DirPath)] + pub placeholder_dir: PathBuf, +} + +impl ToArgs for YosysNextpnrRunEcpPackArgs { + fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { + let Self { placeholder_dir } = self; + args.write_long_option_eq("placeholder-dir", placeholder_dir); + } +} + +#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] +pub struct YosysNextpnrRunEcpPack { + placeholder_dir: Interned, + device: Device, + routed_json_file: Interned, + routed_json_file_name: Interned, + textcfg_file: Interned, + textcfg_file_name: Interned, + frames_file: Interned, + frames_file_name: Interned, + bit_file: Interned, + bit_file_name: Interned, +} + +impl ExternalCommand for YosysNextpnrRunEcpPack { + type AdditionalArgs = YosysNextpnrRunEcpPackArgs; type AdditionalJobData = Self; type BaseJobPosition = GetJobPositionDependencies< - ::BaseJobPosition, + ::BaseJobPosition, >; - type Dependencies = JobKindAndDependencies>; - type ExternalProgram = Xcfasm; + type Dependencies = JobKindAndDependencies>; + type ExternalProgram = Ecppack; fn dependencies() -> Self::Dependencies { Default::default() @@ -966,15 +817,18 @@ impl ExternalCommand for YosysNextpnrTrellis { ::JobsAndKinds, )> { args.args_to_jobs_external_simple(params, global_params, |args, dependencies| { - let YosysNextpnrTrellisArgs { prjtrellis_db_dir } = args.additional_args; + let YosysNextpnrRunEcpPackArgs { placeholder_dir } = args.additional_args; let base_job = dependencies.get_job::(); let frames_file = base_job.file_with_ext("frames"); let bit_file = base_job.file_with_ext("bit"); Ok(Self { - prjtrellis_db_dir: prjtrellis_db_dir.intern_deref(), + placeholder_dir: placeholder_dir.intern_deref(), device: dependencies.job.job.additional_job_data().device, - fasm_file: dependencies.job.job.additional_job_data().fasm_file, - fasm_file_name: dependencies.job.job.additional_job_data().fasm_file_name, + //fixme glue code + routed_json_file: dependencies.job.job.additional_job_data().routed_json_file, + routed_json_file_name: dependencies.job.job.additional_job_data().routed_json_file_name, + textcfg_file: dependencies.job.job.additional_job_data().textcfg_file, + textcfg_file_name: dependencies.job.job.additional_job_data().textcfg_file_name, frames_file, frames_file_name: frames_file .interned_file_name() @@ -989,34 +843,32 @@ impl ExternalCommand for YosysNextpnrTrellis { fn inputs(job: &ExternalCommandJob) -> Interned<[JobItemName]> { [JobItemName::Path { - path: job.additional_job_data().fasm_file, + path: job.additional_job_data().routed_json_file, }] .intern_slice() } fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]> { [ - job.additional_job_data().frames_file, job.additional_job_data().bit_file, ] .intern_slice() } fn command_line_args(job: &ExternalCommandJob, args: &mut W) { - let job_data @ YosysNextpnrTrellis { + let job_data @ YosysNextpnrRunEcpPack { + placeholder_dir, device, - fasm_file_name, + routed_json_file_name, + textcfg_file_name, frames_file_name, bit_file_name, .. } = job.additional_job_data(); - args.write_arg("--sparse"); - args.write_long_option_eq("db-root", job_data.db_root()); - args.write_long_option_eq("part", device.trellis_part()); - args.write_long_option_eq("part_file", job_data.part_file()); - args.write_long_option_eq("fn_in", fasm_file_name); - args.write_long_option_eq("frm_out", frames_file_name); - args.write_long_option_eq("bit_out", bit_file_name); + args.write_arg("--compress"); + args.write_long_option_eq("freq", "38.8"); //FIXME do not hardcode + args.write_long_option_eq("input",textcfg_file_name); + args.write_long_option_eq("bit",bit_file_name); } fn current_dir(job: &ExternalCommandJob) -> Option> { @@ -1024,17 +876,18 @@ impl ExternalCommand for YosysNextpnrTrellis { } fn job_kind_name() -> Interned { - "yosys-nextpnr-trellis".intern() + "yosys-nextpnr-ecp5".intern() } } +//end pub(crate) fn built_in_job_kinds() -> impl IntoIterator { [ - DynJobKind::new(YosysNextpnrTrellisWriteYsFileJobKind), - DynJobKind::new(ExternalCommandJobKind::::new()), - DynJobKind::new(YosysNextpnrTrellisWriteXdcFileJobKind), - DynJobKind::new(ExternalCommandJobKind::::new()), - DynJobKind::new(ExternalCommandJobKind::::new()), + DynJobKind::new(YosysNextpnrWriteYsFileJobKind), //working + DynJobKind::new(ExternalCommandJobKind::::new()), //working + DynJobKind::new(YosysNextpnrWritePcfFileJobKind), //TODO + DynJobKind::new(ExternalCommandJobKind::::new()), //working + DynJobKind::new(ExternalCommandJobKind::::new()), //working ] } diff --git a/nextpnr.txt b/nextpnr.txt new file mode 100644 index 0000000..85d5678 --- /dev/null +++ b/nextpnr.txt @@ -0,0 +1,5 @@ +nextpnr-ecp5 for orangecrab +nextpnr-ice40 for other one* + +modified: Makefile +modified: crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs diff --git a/tools/firrtl.tar.gz b/tools/firrtl.tar.gz new file mode 100644 index 0000000..1676917 Binary files /dev/null and b/tools/firrtl.tar.gz differ