diff --git a/crates/fayalite/src/firrtl.rs b/crates/fayalite/src/firrtl.rs index fa3bb36..28df85a 100644 --- a/crates/fayalite/src/firrtl.rs +++ b/crates/fayalite/src/firrtl.rs @@ -1907,7 +1907,8 @@ impl<'a> Exporter<'a> { additional_fields: (*additional_fields).into(), }, Annotation::Xilinx(XilinxAnnotation::XdcLocation(_)) - | Annotation::Xilinx(XilinxAnnotation::XdcIOStandard(_)) => return, + | Annotation::Xilinx(XilinxAnnotation::XdcIOStandard(_)) + | Annotation::Xilinx(XilinxAnnotation::XdcCreateClock(_)) => return, }; self.annotations.push(FirrtlAnnotation { data, diff --git a/crates/fayalite/src/module/transform/visit.rs b/crates/fayalite/src/module/transform/visit.rs index 0aac2e0..2c33a76 100644 --- a/crates/fayalite/src/module/transform/visit.rs +++ b/crates/fayalite/src/module/transform/visit.rs @@ -33,7 +33,9 @@ use crate::{ sim::{ExternModuleSimulation, value::DynSimOnly}, source_location::SourceLocation, ty::{CanonicalType, Type}, - vendor::xilinx::{XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation}, + vendor::xilinx::{ + XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation, + }, wire::Wire, }; use num_bigint::{BigInt, BigUint}; diff --git a/crates/fayalite/src/vendor/xilinx.rs b/crates/fayalite/src/vendor/xilinx.rs index b406610..d80f388 100644 --- a/crates/fayalite/src/vendor/xilinx.rs +++ b/crates/fayalite/src/vendor/xilinx.rs @@ -8,6 +8,7 @@ use crate::{ prelude::{DynPlatform, Platform}, }; use clap::ValueEnum; +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; use std::fmt; @@ -25,11 +26,18 @@ pub struct XdcLocationAnnotation { pub location: Interned, } +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct XdcCreateClockAnnotation { + /// clock period in nanoseconds + pub period: NotNan, +} + make_annotation_enum! { #[non_exhaustive] pub enum XilinxAnnotation { XdcIOStandard(XdcIOStandardAnnotation), XdcLocation(XdcLocationAnnotation), + XdcCreateClock(XdcCreateClockAnnotation), } } diff --git a/crates/fayalite/src/vendor/xilinx/arty_a7.rs b/crates/fayalite/src/vendor/xilinx/arty_a7.rs index cf8e805..0559199 100644 --- a/crates/fayalite/src/vendor/xilinx/arty_a7.rs +++ b/crates/fayalite/src/vendor/xilinx/arty_a7.rs @@ -3,7 +3,10 @@ use std::sync::OnceLock; +use ordered_float::NotNan; + use crate::{ + annotations::Annotation, intern::{Intern, Interned}, module::{instance_with_loc, reg_builder_with_loc, wire_with_loc}, platform::{ @@ -13,7 +16,7 @@ use crate::{ }, prelude::*, vendor::xilinx::{ - Device, XdcIOStandardAnnotation, XdcLocationAnnotation, + Device, XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, primitives::{self, BUFGCE, STARTUPE2_default_inputs}, }, }; @@ -165,7 +168,11 @@ impl Platform for ArtyA7Platform { ld6, ld7, } = peripherals; - let make_buffered_input = |name: &str, location: &str, io_standard: &str, invert: bool| { + let make_buffered_input = |name: &str, + location: &str, + io_standard: &str, + additional_annotations: &[Annotation], + invert: bool| { let pin = m.input_with_loc(name, SourceLocation::builtin(), Bool); annotate( pin, @@ -179,6 +186,7 @@ impl Platform for ArtyA7Platform { value: io_standard.intern(), }, ); + annotate(pin, additional_annotations); let buf = instance_with_loc( &format!("{name}_buf"), primitives::IBUF(), @@ -210,7 +218,16 @@ impl Platform for ArtyA7Platform { connect(buf.T, false); buf.I }; - let clk100_buf = make_buffered_input("clk100", "E3", "LVCMOS33", false); + let clock_annotation = XdcCreateClockAnnotation { + period: NotNan::new(1e9 / clk100.ty().frequency()).expect("known to be valid"), + }; + let clk100_buf = make_buffered_input( + "clk100", + "E3", + "LVCMOS33", + &[clock_annotation.into()], + false, + ); let startup = instance_with_loc( "startup", STARTUPE2_default_inputs(), @@ -222,12 +239,13 @@ impl Platform for ArtyA7Platform { if let Some(clk100) = clk100.into_used() { connect(clk100.instance_io_field().clk, clk100_sync.O); } - let rst_buf = make_buffered_input("rst", "C2", "LVCMOS33", true); + let rst_buf = make_buffered_input("rst", "C2", "LVCMOS33", &[], true); let rst_sync_cd = wire_with_loc( "rst_sync_cd", SourceLocation::builtin(), ClockDomain[AsyncReset], ); + annotate(clk100_sync.O, clock_annotation); connect(rst_sync_cd.clk, clk100_sync.O); connect(rst_sync_cd.rst, rst_buf.to_async_reset()); let [rst_sync_0, rst_sync_1] = std::array::from_fn(|index| { diff --git a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs index 70c74a9..97cf9d2 100644 --- a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs +++ b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs @@ -19,7 +19,8 @@ use crate::{ prelude::JobParams, util::job_server::AcquiredJob, vendor::xilinx::{ - Device, XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation, XilinxArgs, + Device, XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, + XilinxAnnotation, XilinxArgs, }, }; use eyre::Context; @@ -390,7 +391,7 @@ impl YosysNextpnrXrayWriteXdcFile { output, "set_property LOC {} [get_ports {}]", tcl_escape(location), - tcl_escape(port.scalarized_name()) + tcl_escape(port.scalarized_name()), )?, Annotation::Xilinx(XilinxAnnotation::XdcIOStandard(XdcIOStandardAnnotation { value, @@ -398,7 +399,14 @@ impl YosysNextpnrXrayWriteXdcFile { output, "set_property IOSTANDARD {} [get_ports {}]", tcl_escape(value), - tcl_escape(port.scalarized_name()) + tcl_escape(port.scalarized_name()), + )?, + Annotation::Xilinx(XilinxAnnotation::XdcCreateClock( + XdcCreateClockAnnotation { period }, + )) => writeln!( + output, + "create_clock -period {period} [get_ports {}]", + tcl_escape(port.scalarized_name()), )?, } } diff --git a/crates/fayalite/visit_types.json b/crates/fayalite/visit_types.json index 5b973d8..04227ef 100644 --- a/crates/fayalite/visit_types.json +++ b/crates/fayalite/visit_types.json @@ -1219,7 +1219,8 @@ "data": { "$kind": "Enum", "XdcLocation": "Visible", - "XdcIOStandard": "Visible" + "XdcIOStandard": "Visible", + "XdcCreateClock": "Visible" } }, "XdcLocationAnnotation": { @@ -1232,6 +1233,11 @@ "$kind": "Opaque" } }, + "XdcCreateClockAnnotation": { + "data": { + "$kind": "Opaque" + } + }, "Target": { "data": { "$kind": "Enum",